swift push + node js apns 연동
ios - appDelegate.swift
import UIKit
import RealmSwift
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
let userId_G = UserPreferences.sharedInstance.getUserId() ?? ""
var window: UIWindow?
//MARK: 최초화면
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
print("[!!]Realm DB 위치 = \(Realm.Configuration.defaultConfiguration.fileURL!)")
//MARK:푸시 토큰 권한 묻기
registerForRemoteNotifications()
let coordinator = SiginCoordinator()
let navCon = coordinator.showFirstPage()
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = navCon
window?.makeKeyAndVisible()
return true
}
//MARK:문제집 리스트 조회 api
/// 문제집 리스트 조회 api
public func loadQuestionsDatas(complete: @escaping (Bool)-> Void){
/// 테이블뷰 데이터 배열 (문제집)
var items = [QuestionVO]()
HttpAdapter(method: .POST, service: .questionListByAppCode, param: ["code" : APP.CODE.rawValue, "userId" : userId_G]).request { data in
if let result = data{
let data = result["rows"] as? Array<[String:Any]>
if let data = data{
for i in 0 ..< data.count {
let questionVo = QuestionVO()
let questionsData = questionVo.parser(data: data[i])
if let data = questionsData {
/// 문제집 이름 -> 초성 중성 종성으로 변환 후 저장
data.nameChoIndex = ChosungUtil.getUTF8StringCho(data.name)
data.nameChoJungJongIndex = ChosungUtil.getUTF8StringChoJungJong(data.name)
/// 문제집 설명 -> 초성 중성 종성으로 변환 후 저장
data.descChoIndex = ChosungUtil.getUTF8StringCho(data.desc)
data.descChoJungJongIndex = ChosungUtil.getUTF8StringChoJungJong(data.desc)
//MARK: TableView 배열 삽입
items.append(data)
}
}//for - end
}//data = data - end
//MARK: 문제집 리스트 정보 앱디비에 저장
DispatchQueue.main.async {
QuestionVO.insert(objects: items)
}
complete(true)
}else{
complete(false)
}
}//Api-call-end
}
//MARK: 푸시 토큰 권한
/// 푸시 토큰 권한
private func registerForRemoteNotifications() {
// 1. 푸시 center (유저에게 권한 요청 용도)
let center = UNUserNotificationCenter.current()
// push처리에 대한 delegate - UNUserNotificationCenterDelegate
center.delegate = self
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
center.requestAuthorization(options: options) { (granted, error) in
/// 승인 받았는지 여부 체크
guard granted else {
print("유저가 푸시 알림을 거부했습니다.")
return
}
DispatchQueue.main.async {
print("유저가 푸시 알림을 허용했습니다.")
// 2. APNs에 디바이스 토큰 등록
UIApplication.shared.registerForRemoteNotifications()
}
}
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
// 앱이 foreground상태 일 때, 알림이 온 경우 처리
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// 푸시가 오면 alert, badge, sound표시를 하라는 의미
completionHandler([.banner, .list])
}
/// push가 온 경우 처리
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
// deep link처리 시 아래 url값 가지고 처리
let pushData = response.notification.request.content.userInfo
print("pushData = \(pushData)")
let apnsDic = pushData["aps"] as? [String:String]
let msgString = apnsDic?["alert"] ?? ""
let payloadString = apnsDic?["payload"] ?? ""
print("msgString = \(msgString)")
print("payloadString = \(payloadString)")
// if url.containts("receipt")...
}
//MARK: APNS로 부터 응답처리
///- 디바이스 토큰 등록 성공 시 실행되는 메서드
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenString = deviceToken.map { String(format: "%02x", $0) }.joined()
print("발급된 토큰 : \(deviceTokenString)")
}
///- 디바이스 토큰 등록 실패 시 실행되는 메서드
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("토큰 등록 실패")
}
}
node js
var express = require('express');
var router = express.Router();
var loger = require('../../config/logmodule.js'); //로그모듈
var path = require('path');
var apn = require('apn');
const logger = require('../../config/logmodule.js');
loger.info("메모리 로딩 시작. - admin.js");
/* send push */
router.get('/sendpush', function (req, res, next) {
loger.debug("push 페이지 진입 ")
let publicPath = path.join(__dirname, "../../public");
loger.debug("p8 인증서 경로 : " + publicPath + '/푸시인증서.p8')
// Set up apn with the APNs Auth Key
var apnProvider = new apn.Provider({
token: {
key: publicPath + '/푸시인증서.p8',
keyId: '',
teamId: '',
},
production: false // 개발용
});
// 디바이스 토큰
var deviceToken = '디바이스 토큰!!';
// Prepare a new notification
var notification = new apn.Notification();
// 앱 번들아이디
notification.topic = '';
// Set expiration to 1 hour from now (in case device is offline)
notification.expiry = Math.floor(Date.now() / 1000) + 3600;
// 배지 표시
//notification.badge = 3;
// 사운드
//notification.sound = 'ping.aiff';
notification.alert = "\uD83D\uDCE7 \u2709 You have a new message";
// Send any extra payload data with the notification which will be accessible to your app in didReceiveRemoteNotification
notification.payload = {'id': '123'};
// 실제로 푸시 발송하는 함수
apnProvider.send(notification, deviceToken).then(function (result) {
if (result.failed.length == 0) {
console.log(result);
loger.debug("푸시 발송 성공 : " + result.sent)
res.json({
result: 'success',
tocken: '푸시 발송 성공'
});
} else {
loger.debug("푸시 발송 실패 ")
res.json({
result: 'fail',
tocken: '푸시 발송 실패'
});
}
});
});
module.exports = router;
loger.info("메모리 로딩 완료. - push.js");
참고 소스
https://nicgoon.tistory.com/202
http://webs.co.kr/index.php?document_srl=3319441&mid=apple
https://runlife.tistory.c
'아이폰 개발 > Swift' 카테고리의 다른 글
swift 채팅앱 3 TableView CustomCell Performance (0) | 2021.07.31 |
---|---|
swift 채팅앱 - keyBoard notification (0) | 2021.07.31 |
swift 채팅앱 디자인 레이아웃 만들기 - 1 (1) | 2021.07.27 |
swift 테이블뷰 셀의 동적 높이 (0) | 2021.07.27 |
swift autolayout - 그래프를 통한 오토레이아웃의 동적 컨트롤 (0) | 2021.07.24 |