Things take time

[SWIFT] APNS, 푸시에 관한 설정(receive event, click(tap) event) 본문

iOS (기능)

[SWIFT] APNS, 푸시에 관한 설정(receive event, click(tap) event)

겸손할 겸 2018. 1. 12. 09:04

[APNS]


기본적인 푸시 세팅에 대한 방법은 아래와 같이 포스팅에 따로 두었다.


(Node.js : http://g-y-e-o-m.tistory.com/72)

(PHP : http://g-y-e-o-m.tistory.com/24)


참고로 PHP는 각 인증파일을 pem으로 생성했는데, 이제는 p8파일 하나로 통합적으로 사용할 수 있다. 그러므로 1년마다 갱신하는 pem보다는 영구적이며, 한 개발자가 만든 모든 앱을 통합적으로 사용할 수 있는 p8파일을 사용하도록하는 것이 좋겠고, p8파일을 사용하여 APNS 서버와 통신하는 PHP소스는 구글링을 통해 찾아봐야 한다. (노드는 p8 기준으로 작성됨)


이 포스팅을 참고/정리한 곳이다. 푸시에 대한 기본 세팅도 알려주므로, 모르는 사람은 이 곳을 참조해도 괜찮을듯 (단, 이 포스팅도 pem파일 기준임)

https://www.raywenderlich.com/156966/push-notifications-tutorial-getting-started



[응용]


어찌되었든, 푸시를 받기 위해 세팅하고 서버에서 작성한 스크립트의 개요는 이미 알았다고 가정하고 진행한다.

푸시를 받는것에서 끝나는게 아니라 푸시를 받았을 때와 푸시 메시지를 클릭했을 때, 그리고 현재 디바이스가 foreground인지, background인지, inactive인지에 따라 처리하는 로직이 다 다르므로, 이 것을 다 알고 있어야 나중에 응용할 때도 유용할 것이다.


기본적으로 푸시를 받았을 때 처리하는 클래스, swift파일은

AppDelegate.swift 이다.


앱이 처음 켜졌을때, 앱이 켜졌을 때, 백그라운드로 들어갔을 때 등.. 여러 앱의 생명주기를 컨트롤할 수 있다.

여기서 기본적으로, UNUserNotificationCenterDelegate 프로토콜을 상속받았다 가정하고 진행한다.


해당 딜리게이트를 상속받게 되면, 그 안에 들어가서 보면 아래와 같이 두개의 함수를 오버라이드 할  수 있다.



두 함수가 핵심이다. 


첫 번째 함수는 앱이 켜져 있는 상태(foreground)에서 푸시를 받았을 때 호출 되는 함수

두 번째 함수는 앱이 켜져 있지는 않지만 백그라운드로 돌고 있는 상태에서 푸시를 클릭하고 들어왔을 때 혹은 알림이 dismiss될 때 호출되는 함수


이다. 그러므로 필요한 상황에 맞춰 사용하면 될 것이다.


그리고 한 가지 가정을 더,

푸시를 클릭하고 들어왔지만, 앱이 꺼져있는.. 완전히 종료된 상태에서 푸시 메시지를 클릭했을 때 호출되는 함수는 어떤 것일까.


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {}


이 함수이다. 앱이 처음 켜졌을 때 호출되는 함수로써 푸시메시지를 등록하거나, 업데이트를 체크하거나 이런 애들을 기록하는 것인데, 여기서 launchOptions라는 저 파라미터를 분석하면, 푸시메시지를 클릭하고 들어왔는지에 대한 컨트롤이 가능하다.

// 푸시를 클릭해서 앱이 처음 켜진 경우 ,Dictionary
            if let notification = launchOptions?[.remoteNotification] as? [String:AnyObject]{
                let aps = notification["aps"] as! [String : AnyObject]
                
                ...
            }

이 부분을 appliation함수내에 didFinish.. 에 사용하면 된다.


즉, 결론은


1. 앱은 꺼져있는데 푸시를 받고, 해당 푸시를 클릭했을 때

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {}


2. 앱이 현재 화면에서 실행되고 있을 때

    @available(iOS 10.0, *)

    public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Swift.Void){}


3. 앱은 꺼져있지만 완전히 종료되지 않고 백그라운드에서 실행중일 때

    @available(iOS 10.0, *)

    public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Swift.Void){}


그리고 2,3번은 UNUserNotificationCenterDelegate를 사용해야 한다.


푸시 메시지를 분석하는 방법은 1번의 경우 위의 launchOptions를 사용하고, 3번은 response.notification.request.content.userInfo를 얻어서 해당 info를 위처럼 ["aps"] as! [String: AnyObject]로 하면 된다.


[액션]


푸시기능에는 액션이란 것이 있어서 푸시 메시지(노티라고 함)에 버튼을 달거나 하는 기능을 추가할 수 있다.

            center.requestAuthorization(options: [.badge, .alert, .sound]) {
                (granted, error) in
                print("Push Permission : \(granted)")
                
                guard granted else {
                    return
                }
                
                // Category사용 예, 서버쪽에서도 viewCategory라는 이름으로 등록해야 한다. note.category = "viewCategory"
                let viewAction = UNNotificationAction(identifier: "viewAction", title: "View", options: [UNNotificationActionOptions.foreground])
                let viewCategory = UNNotificationCategory(identifier: "viewCategory", actions: [viewAction], intentIdentifiers: [], options: [])
                center.setNotificationCategories([viewCategory])
                
                
                self.getNotificationSettings()
            }

여기서 가운데 로직만 보면 된다. 그리고 서버 푸시 발송함수에는 category항목에 category의 identifier(여기선 viewCategory)값을 넣어 보내주면 받는 디바이스에서는 액션값이 사용되어, 포어그라운드 상태일때 해당 푸시를 드래그하면 버튼이 생기게 된다.