iOS
mBaas
NCMB
Swift
ios10

【Swift】いまさらですがiOS10でプッシュ通知を実装したサンプルアプリを作ってみた

iOS10のプッシュ通知はこんな感じ

iOS10のプッシュ通知は、今までとはデザインが違いますね。
コードもSwift3になったので、違います。
Swift3が出てきてからもうかなり時間が経ってしましましたが…きっと、これから実装される方もいるはず!
ぜひご参考にしていただけるかと思います。

295.png

サンプル

動作環境と事前準備

推奨動作環境

  • Mac OS Sierra 10.12 以上
  • Xcode8 以上
  • iPhone iOS 10 以上

事前準備

サンプルプロジェクト一覧

すべて自由に使ってOKです▼

言語 プッシュ通知 リッチプッシュ ペイロード取得
Swift SwiftPushApp SwiftRichPushApp SwiftPaylpadApp
  • 上記3つのサンプルを用意しました
    • 通常のプッシュ通知のみ実装した、SwiftPushApp
    • SwiftPushAppに加えて、プッシュ通知を開くとWebViewを表示できるリッチプッシュ機能を実装した、SwiftRichPushApp
    • SwiftPushAppに加えて、配信したプッシュ通知からメッセージなどのデータを取得するペイロード機能を実装した、SwiftPayloadApp
  • 使い方は各リンク先のREADMEにしたがってください◎
  • それぞれについて次でコード解説します('▼'*♪

コード紹介

そもそもプッシュ通知の仕組みって?

iOSの場合はAPNsというApple社のプッシュ通知用サーバーを介してプッシュ通知は配信されます。
下図のように①~⑤の流れでプッシュ通知は端末に届きます。

095.png

この中で「②デバイストークン発行」でAPNsから発行されたデバイストークンを端末で取得し、サーバー側に保存する処理は、アプリ側に実装する必要があります。

<プッシュ通知の基本>デバイストークンの取得とサーバーへの登録

AppDelegate
import UIKit
import UserNotifications
import NCMB

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    var window: UIWindow?

    // APIキーの設定
    let applicationkey = "YOUR_NCMB_APPLICATIONKEY"
    let clientkey      = "YOUR_NCMB_CLIENTKEY"

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

        // SDKの初期化
        NCMB.setApplicationKey(applicationkey, clientKey: clientkey)

        // デバイストークンの要求
        if #available(iOS 10.0, *){
            /** iOS10以上 **/
            let center = UNUserNotificationCenter.current()
            center.requestAuthorization(options: [.alert, .badge, .sound]) {granted, error in
                if error != nil {
                    // エラー時の処理
                    return
                }
                if granted {
                    // デバイストークンの要求
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }
        } else {
            /** iOS8以上iOS10未満 **/
            //通知のタイプを設定したsettingを用意
            let setting = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            //通知のタイプを設定
            application.registerUserNotificationSettings(setting)
            //DevoceTokenを要求
            UIApplication.shared.registerForRemoteNotifications()
        }

        // MARK: アプリが起動されるときに実行される処理を追記する場所


        return true
    }

    // デバイストークンが取得されたら呼び出されるメソッド
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // 端末情報を扱うNCMBInstallationのインスタンスを作成
        let installation : NCMBInstallation = NCMBInstallation.current()
        // デバイストークンの設定
        installation.setDeviceTokenFrom(deviceToken)
        // 端末情報をデータストアに登録
        installation.saveInBackground {error in
            if error != nil {
                // 端末情報の登録に失敗した時の処理                
            } else {
                // 端末情報の登録に成功した時の処理
            }
        }
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // MARK: アプリが起動しているときに実行される処理を追記する場所

    }
}

リッチプッシュの処理

リッチプッシュって何?

  • プッシュ通知にURLを載せて配信し、プッシュ通知開封時にWebビューで表示することができる機能です

001.png

  • 実装は簡単で、上記デバイストークン処理のコードに加え、コメント(// MARK:)の2箇所(処理を実行するタイミング)にそれぞれに下記のコードを追記するだけです◎
リッチプッシュを表示させる処理
// MARK: アプリが起動されるときに実行される処理を追記する場所
if let userInfo = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as! [AnyHashable : Any]! {
    // リッチプッシュを表示させる処理
    NCMBPush.handleRichPush(userInfo)
}

// MARK: アプリが起動しているときに実行される処理を追記する場所
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    // リッチプッシュを表示させる処理
    NCMBPush.handleRichPush(userInfo)
}

ペイロードの処理

ペイロードって何?

  • プッシュ通知にJSONデータを持たせて配信し、開封時にプッシュ通知からデータを取得することができる機能です
  • ペイロードとして取得したデータは、アプリ内で使用することが可能です

Payload.png

  • リッチプッシュと同様に、コメント(// MARK:)の2箇所(処理を実行するタイミング)にそれぞれに下記のコードを追加することでデータを取得可能です
    • サンプルアプリではその表示までを実装しています!
ペイロードからデータを取得する処理
// MARK: アプリが起動されるときに実行される処理を追記する場所
if let userInfo = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as! [AnyHashable : Any]! {
    // ペイロードからデータを取得する処理
    let key: Array! = Array(userInfo .allKeys)
    let value: Array! = Array(userInfo .allValues)

    if key != nil && value != nil {
        for i in 0..<key.count {
            let key0 = key[i] as! String
            payloadKeyData.append(key0)
            let value0 = String(describing: value[i])
            payloadValueData.append(value0)
        }

    }    
}

// MARK: アプリが起動しているときに実行される処理を追記する場所
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    // ペイロードからデータを取得する処理
    let key: Array! = Array(userInfo.keys)
    if key != nil {
        for i in 0..<key.count {
            let key0 = key[i] as! String
            let value0 = userInfo["\(key0)"]
            payloadKeyData.append(key0)

            if let unwrapValue = value0 {
                if key0 == "aps" {
                    let apsUnwrapValue = String(describing: unwrapValue)
                    payloadValueData.append(apsUnwrapValue)
                } else {
                    payloadValueData.append(unwrapValue as! String)
                }
            }
        }
    }
}

※ただし、上記の例では、フィールドに取得したデータの格納用配列を準備します

AppDelegate.swift
// payload
var payloadKeyData: Array<String> = []
var payloadValueData: Array<String> = []

参考

GitHubにたくさんサンプルアプリを公開しています!
https://github.com/natsumo/