post Image
プッシュ通知を究める!その①〜普通のプッシュ通知の実装の仕方〜

iOS10になってからプッシュ通知もいろいろ進化しました!各種プッシュ通知をどうやって実装するんですか?と聞かれることが多いのでまとめていきたいと思います。

以下予定

まずは普通のプッシュ通知の実装の仕方から

※証明書の作成などは以前から特に変わっていないので省きます。

検証環境:Xcode8.2.1, Swift3.0

iOS10からのプッシュ通知の実装の仕方

iOS10からはUserNotification.frameworkを使えるようになりました。iOS9以前と比べるとちょっと変わった部分がありますのでまずはそれを復習していきましょう。

プッシュ通知のCapabilitiesをONにする

まずはCapabilitiesにて「Push Notifications」を「ON」にします。
するとプロジェクト名.entitlementsというファイルが生成されます。

Screen_Shot_2017-01-12_at_2_42_43_PM.png

こいつがないと下記のエラーが出てプッシュ通知の登録ができません。

Remote Notification Error: no valid 'aps-environment' entitlement string found for application

プッシュ通知の登録をする

UserNotification.frameworkをimportします。さらにプッシュ通知を有効にするために下記を実装します。

AppDelegate.swift
import UIKit
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

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

        if #available (iOS 10.0, *) {
            let center = UNUserNotificationCenter.current()
            center.requestAuthorization(options: [.sound, .alert, .badge], completionHandler: {
                (granted, error) in

                if granted == true {
                    // プッシュ通知の登録      
                    application.registerForRemoteNotifications()
                } else {
                    // プッシュ通知を許可しなかった場合
                }
            })
        } else {
            // iOS9までのプッシュ通知のsetting
        }
        return true
    }

(余談:ここではdidFinishLaunchingWithOptionsのタイミングで登録していますが、プッシュ通知の許可をしてもらいやすくするために別のタイミングで行うのもありです。別途どっかで書きます。)

初めてrequestAuthorizationが呼ばれた時には下記のようなプッシュ通知の許諾ダイアログが表示されます。

IMG_9104.png

こいつで「Allow」を押すとgrantedがtrueで渡ってきます。grantedがtrueだったらregisterForRemoteNotifications()を呼んでプッシュ通知の登録をします。

(余談:この分岐を書かなくてもgrantedがfalseだった場合はregisterForRemoteNotifications()を呼んでも後述するdeviceTokenの取得はできないようです。)

deviceTokenを取得する

プッシュ通知の宛先となるdeviceTokenを取得するために下記のメソッドを実装します。

AppDelegate.swift
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

        let token = String(format: "%@", deviceToken as CVarArg) as String
        print("deviceToken: \(token)")
        // プッシュ通知送信サービスを使ってたらSDKにdeviceTokenセットしたりする

    }

registerForRemoteNotifications()が呼ばれると下記のメソッドが呼ばれます。引数としてdeviceTokenが渡ってくるのでこれを取得し、プッシュ通知を送信するのに用います。プッシュ通知を送信するサービスを使っていればここでそのサービスのSDKにdeviceTokenを渡したりします。

(余談:ネットワークが通じていないとここでdeviceTokenは取得できないようです。deviceTokenの取得は次回ネットワークが通じている時になります。deviceTokenの取得にはAPNsとの通信が必要なので当然ちゃ当然ですかね。)

プッシュ通知を開いた時の処理を記述する(オプショナル)

プッシュ通知に関するUNUserNotificationCenterDelegateには下記2つのデリゲートメソッドがあります。

  • didReceiveを実装すると プッシュ通知のバナーをタップしたり、通知センターの通知をタップしてアプリを起動した時 にこいつが呼ばれるようになります。didReceiveというメソッド名ですがプッシュ通知を受け取った時ではなく、プッシュ通知からアプリが起動されたタイミングで呼ばれます。「プッシュ通知をタップしたら特定のページに遷移する」などをプッシュ通知からアプリを起動した時に特定の処理をしたい場合に用います(本当にプッシュ通知を「受け取った時」に何かを処理したい場合については別途どっかで書きます)。

  • willPresentアプリがアクティブな状態(アプリがすでに開かれている状態)でプッシュ通知のバナーを表示したりしたい場合 にこいつを実装します(iOS9まではアプリがアクティブの状態で通知は表示できなかった)。completionHandler([.badge, .sound, .alert])に渡すOptionsによって通知の挙動を変えたりすることができます。

以下実装例です。

デリゲートの宣言&デリゲートメソッドを実装します。

AppDelegate.swift
extension AppDelegate: UNUserNotificationCenterDelegate {
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

        print("Push Notification will present \(notification)")
        completionHandler([.badge, .sound, .alert])

    }

    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        print("Push Notification did receive \(response)")
        completionHandler()
    }
}

デリゲートオブジェクトをセットします。UNUserNotificationCenterDelegateファイルのコメント中に下記のようにあるのでapplicationDidFinishLaunchingでデリゲートをセットしてやりましょう。

The delegate must be set before the application returns from applicationDidFinishLaunching:.

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

        if #available (iOS 10.0, *) {
            let center = UNUserNotificationCenter.current()

            center.delegate = self  // <-ここを追加

            center.requestAuthorization(options: [.sound, .alert, .badge], completionHandler: {

以上、何か間違い、質問等あればコメントによろしくお願いします!
次はリッチ通知について書く予定です。


『 Swift 』Article List