Edited at

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

More than 1 year has passed since last update.


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/