Things take time

[SWIFT] iOS10에 추가된 UserNotifications을 사용하자 (푸시, APNS) 본문

iOS (기능)

[SWIFT] iOS10에 추가된 UserNotifications을 사용하자 (푸시, APNS)

겸손할 겸 2017. 12. 6. 17:28

[개요]


기본적으로 APNS에서 푸시를 받을 때 사용하는 메소드, 함수는 UIApplicationDelegate 프로토콜을 상속받아 사용하는 


func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Swift.Void


함수를 사용할 것이다. 물론 아직까지도 사용할 수 있다(푸시를 보내는 서버쪽에서 content-available을 1로 설정할 경우, 혹은 iOS 10미만의 디바이스는 이 함수를 탄다)


얘를 제외한, fetchCompletionHandler가 없는 didReceiveRemoteNotification 함수는 deprecated되었으므로 사용하지 않아야한다.


아직까지는 사용할 수 있다 하더라도, 이 함수보다는 iOS 10이상에서 지원하는 userNotificationCenter함수를 사용하는 것이 옳다는 것이 개요이다.


[사용법]

import UIKit import UserNotifications @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { if #available(iOS 10.0, *){ let center = UNUserNotificationCenter.current() center.delegate = self /* custom action + category : 사용할 경우 조사, 참고용 let content = UNMutableNotificationContent() let repeatAction = UNNotificationAction(identifier:"repeat",title:"Repeat",options:[]) let changeAction = UNTextInputNotificationAction(identifier: "change", title: "Change Message", options: []) let closeAction = UNNotificationAction (identifier : "comment-close" , title : "Close" , options : [UNNotificationActionOptions.destructive]) let category = UNNotificationCategory(identifier: "actionCategory", actions: [repeatAction, changeAction, closeAction], intentIdentifiers: [], options: []) content.categoryIdentifier = "actionCategory" UNUserNotificationCenter.current().setNotificationCategories([category]) */ center.requestAuthorization(options: [.badge, .alert, .sound]) { (granted, error) in if(granted){ print("사용자가 푸시를 허용했습니다") // 11/13 메인 쓰레드 관련 경고로 수정함 DispatchQueue.main.async { application.registerForRemoteNotifications() } } else { print("사용자가 푸시를 거절했습니다") } } } else{ UIApplication.shared.registerForRemoteNotifications() } return true }

체크해야 할 점은 UserNotifications를 import하고 delegate를 상속받으며 delegate=self 작업을 해준다는 것이다.

그리고 해당 프로토콜이 갖고 있는 함수 두 개를 가져다 쓰면 된다. 주석 부분은 개인 공부용이므로 무시

// The method will be called on the delegate only if the application is in the foreground. The application can choose to have the notification presented as a sound, badge, alert and/or in the notification list. @available(iOS 10.0, *) public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Swift.Void){ print("Foreground") completionHandler([.alert, .badge, .sound]) } // The method will be called on the delegate when the user responded to the notification by opening the application, dismissing the notification or choosing a UNNotificationAction. The delegate must be set before the application returns from application:didFinishLaunchingWithOptions:. // 기본적으로 메시지가 닫혔을 때, 푸시메시지를 클릭했을 때 라는 두개의 액션을 Default로 갖고 있다. 이 뿐만아니라 커스텀 액션을 하려면 application:didFinishLaunchingWithOptions에서 카테고리 및 액션을 등록하고 서버에서도 이에 맞춰서 등록해야 함(조사 필) @available(iOS 10.0, *) public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Swift.Void){ let notification = response.notification let userInfo = notification.request.content.userInfo if response.actionIdentifier == UNNotificationDismissActionIdentifier { print ("Message Closed") } else if response.actionIdentifier == UNNotificationDefaultActionIdentifier { print ("푸시 메시지 클릭 했을 때") guard let info = userInfo["aps"] as? Dictionary else {

return } print(info) guard let mainVC = self.window?.rootViewController as? MainViewController else{ return } // 여기서 위의 받았을 때 mainVC나 이동로직 이상하게 쓰면 UNUserNotificationCenterDelegate methods not being called 나옴 } completionHandler() }

그리고 해당 프로토콜이 갖고 있는 이 두개의 함수가 기존의 appication함수를 대체하게 되었다.

하나는 앱이 켜져있을 때 푸시를 받았을때, 동작하는 함수로 메시지, 뱃지, 사운드를 서버에서 보낸 것을 다 받아 띄우겠다는 의미이다. 참고로 안드로이드와 달리 아이폰은 앱이 꺼져있을 때 뱃지 처리를 네이티브에서 할 수없고, 오로지 서버에서만 처리해야한다.


그리고 아래의 함수에서는 각 푸시에 대한 액션에 대한 처리를 하게된다. 따로 커스텀 액션을 지정하지 않으면 메시지 닫혔을때(이때가 언제인지 아직 확인 못함), 메시지를 클릭하고 앱이 켜졌을때에 대한 동작을 할 수 있다. 후자의 경우가 가장 많이 쓰이므로, 각 개별 환경에 맞게 소스로  세팅해주면 되겠다.


그리고 기본적은 서버 푸시발송(Node.js : http://g-y-e-o-m.tistory.com/72)(PHP : http://g-y-e-o-m.tistory.com/24)를 참고하면 되겠다.