ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
プッシュ通知のプライマー
ユーザーがAppを最大限に活用できるよう、重要なイベントやアップデートのプッシュ通知を送ったり、Appが最新の状態で起動するようにバックグラウンドでデータを送信したりしましょう。通知を使って、タイムリーで適切な情報をアラートする方法を学びましょう。アラートとバックグラウンド通知の違い、Appに統合する方法や、ジョブに適したAPIを使うことでミスを回避する方法をお伝えします。
リソース
関連ビデオ
WWDC23
-
ダウンロード
こんにちは WWDCへようこそ “プッシュ通知のプライマー” エリオット・ガーナーです このセッションでは プッシュ通知についてお話しします まずプッシュ通知の概要 プッシュ通知とは何なのか― なぜそれを使用するのかについて 説明します それから アプリケーションへ 追加する方法をお話しします プッシュ通知は アプリケーションを 魅力的でインタラクティブなものにします アプリケーションにリアルタイムで 更新を届ける機能を提供します これにより アプリケーションの更新が― 発生する際にダイナミックな体験が 可能になります では アプリケーションに プッシュ通知を追加する 利点はなんでしょう? ひとつは アプリケーションが 最前面になくてもよいことです プッシュ通知はアプリケーションの状態に 関係なく通達され 必要であれば アプリケーションを起動します プッシュ通知は省電力で カスタマーと関わる素晴らしい方法です プッシュ通知には2種類あります alert通知と バックグラウンド通知です alert通知は視覚的にalertを通達し アプリケーションがカスタマイズ できる方法で相互作用します バックグラウンド通知は コンテンツを最新の状態に保つために アプリケーションが最前面にない時に ランタイムを受け取ることができます それでは alert通知からはじめましょう alert通知は 目に見えるalertを通達し アプリケーションの更新を提供します この通知は相互作用可能な 新しい情報について使用されるべきです このalertは アプリケーションの実行を必要とせず アプリケーションの状態に関わらず 表示されます そして最も重要なのは 完全にカスタマイズ可能だということです alertの見た目や 相互作用能力はあなた次第です alert通知のための アプリケーションの設定を開始する方法を 見ていきましょう はじめに リモート通知を 登録する必要があります これはデバイスを― Apple Push Notificationシステム(APNs) へ 登録し― デバイストークンを アプリケーションへ返します このトークンはデバイスを識別するために 使用され 通知の対象にできます 次に AppDelegateに― UNUserNotificationCenterDelegateを 宣言します 完了すると AppDelegateを通知センターの デリゲートとして割り当てます これによりalertが開いた際 アプリケーションに通知されます registerForRemoteNotificationsを呼び出すと これらの2つのうち1つのメソッドで コールバックを受け取ります デバイスへのトークンの取得に失敗すると didFailToRegisterFor RemoteNotificationsWithErrorが― 登録の失敗理由が示されたエラーと共に 呼び出されます
トークンの取得に成功すると そのトークンをバックエンドの プッシュサーバに送り デバイスに通知を送ります 例を見てみましょう デバイストークンがデータオブジェクトとして アプリケーションに通達されます サーバにそれを送るには 文字列に変換する必要があります データをコンポーネントに 分割することで可能です コンポーネントを16進数の文字列に分割し それから単一の文字列に結合し直します そしてその文字列をURLQueryに追加し 完全修飾エンドポイントを作成します
次にURLSessionを実行して― そのトークンをサーバへ送信し データベースに登録します 最後に デバイスが通知を受信する前に― アプリケーションがalertを 表示する権限を要求する必要があります requestAuthorizationを呼び出すと アプリケーションがalertを表示できるか たずねるプロンプトが表示されます
その決定の結果がcompletionHandlerに渡され デバイス設定で設定されます このメソッドを連続して呼び出すと デバイス設定のステータスが返され プロンプトは表示されません ご覧のとおり この関数はalertを表示し 音を鳴らしアプリケーションアイコンに バッジを表示する権限を求めています コンテキストがある場合のみ アクションへ応答して承認を要求します このコンテキストでユーザーの許可を得られる 可能性が はるかに高くなります 通知ペイロードの処理方法をご説明する前に ペイロードの例を見てみましょう レストランのアプリケーションを 構築していて ユーザーに新着のスペシャルを 通知したいとします
ご覧のとおりalertが― アボカドベーコンバーガーが 発売されたことを知らせています このペイロードを1つずつ解析して 確実に理解しましょう 最初にapsディクショナリです apsディクショナリはデバイスに 通知のレンダリング方法を指示します apsディクショナリの内側は alertディクショナリです これは通知に使用するテキストを システムに伝えます その内側にタイトルと 本文フィールドがあります タイトルフィールドは短い文字列で 通知の目的を示します これは短く分かりやすいものである 必要があります 本文フィールドはalertメッセージの 完全な説明文です 次にサウンドフィールドです このフィールドはオプションで alertを受け取る際に デバイスで 音を再生させたい場合 含むべきです デフォルトサウンドを使用したければ このように“default”を使用します また カスタムサウンドも提供できます 次に バッジフィールドです これはアイコンのバッジを変更するのに 使用されるオプションのフィールドです これは絶対値で アプリケーションアイコンに表示されます この値はプログラムで変更できるので alertが開いたら― 通知を処理する際 値を“0”に設定します apsフィールドの外側には 通知と一緒に提供したい― カスタムデータがあります ここではアプリケーションが 今日のスペシャルの内容と その価格を示しています ではペイロードがどのように見えるか 分かったところで 通知の受信を処理する方法を 調べましょう UNUserNotificationCenterDelegateメソッドです 通知が開かれるたびに 呼び出されます このメソッドは completionHandlerを持っていて それは関数から返される前に 呼び出されなくてはなりません アプリケーションに送られたペイロードは 通知のコンテンツのuserInfoプロパティから 取り出せます ペイロードを取得したら JSONのディクショナリ表記から データを解析します データが期待通りにない場合 戻る前にcompletionHandlerを呼び出します これによりシステムに 通知の開始処理の終了が伝えられます データを取得するとアプリケーションに 必要な更新を実行できます alertに関連するアプリケーションの部分を 開く必要があります このレストランの例では alertがタップされると アイテムがカートに追加され カートが表示されます
完了したら completionHandler呼び出して システムに終了を伝えます これだけです alert通知の処理と受信のために アプリケーションに設定することは これで全てです alert通知の実装については ここまでにして バックグラウンド通知についてと アプリケーションでの その使用方法をお話しします バックグラウンド通知は alert通知に似ていますが 覚えておくべき決定的な違いが いくつかあります バックグラウンド通知は プッシュ通知の受信時に アプリケーションがバックグラウンドから データを読み込めるようにします これはアプリケーションを 実行していない時でも アプリケーションを最新の状態に保つために 使用されるべきです システムはアプリケーションを起動し バックグラウンド更新のために 必要なランタイムを提供します しかしこれにはいくつか制限があります システムはアプリケーションに 1日の多くのバックグラウンド操作を制限し デバイスが特定の制約下にある時 バックグラウンドの更新が実行されません 例えば デバイスのバッテリー残量が 少ない時です ではバックグラウンド通知を処理して 受信するように設定するために 何をする必要があるのでしょうか? alert通知と同様 アプリケーションに デバイストークンを取得するには アプリケーションをリモート通知に 登録する必要があります
しかし alert通知とは異なり アプリケーションに UNUserNotificationCenterDelegateを 設定したり UNUserNotificationCenterに 割り当てたりする必要はありません UNUserNotificationCenterDelegateは alert通知を処理する際にのみ 使用するためです そしてバックグラウンド通知は ここで実装されているもので全てなので それは必要ありません registerForRemoteNotificationsが 呼び出されたため デバイストークンの受信を処理する必要があり 登録のために そのデバイスを プッシュサーバへ送信する必要があります これはalert通知に 必要なことと全く同じです さて バックグラウンド通知のペイロードを 調べてみましょう バックグラウンド通知のペイロードは alert通知のものより随分シンプルです バックグラウンド通知に必要なフィールドは apsディクショナリ内の content availableフィールドのみです
このフィールドは これがバックグラウンド通知であり 更新を実行するためにアプリケーションの起動が 必要であることをシステムに伝えます alert通知のように apsディクショナリの 外側をカスタムデータに使用します それではバックグラウンド通知を 扱う方法をみてみましょう デバイスがリモート通知を受信すると didReceiveRemoteNotificationが 呼び出されます バックグラウンド通知を扱うために このメソッドを使用します
この関数にもcompletionHandlerがあります しかし alert通知を処理する際の completionHandlerと異なり― このcompletionHandlerは 1つのパラメータを持ちます
このパラメータはenumで システムにバックグラウンド更新が 失敗したかどうか― データを受信していないか 新しいデータを受信したか を伝えます これによりシステムが 将来アプリケーションを起動するタイミングを うまくはかれるようになります なので レストランアプリケーション場合 バックグラウンド通知を使用し メニュー内容を毎日最新の状態にするために 毎日メニューを取得しています メニューの最新バージョンのための URL作成に失敗した場合 completionHandlerを呼び出し バックグラウンド更新が失敗したことを伝えます
URLが作成されたら 今日のメニューのデータを取得するために URLSessionの作成が必要です データを受信しなかった場合 completionHandlerを呼び出し データなしでバックグラウンド更新が 正常に終了したことを伝えます
そうでない場合 ここで更新されたメニューが 読み込まれたので アプリケーションはコンテンツの更新に そのデータを使用できます それが完了すると completionHandlerを呼び出し システムに― バックグラウンド更新が成功し 新しいデータを取得したことを通知します
バックグラウンド通知を扱うために アプリケーションへ実装することは これで全てです これで プッシュ通知とは何か― それをどう扱うのか また どう実装するのか説明できたので 問題なくアプリケーションに 追加していただけるはずです デベロッパポータルで プッシュ通知を有効化し このステップに従って アプリケーションへ プッシュ通知を追加するだけです
サンプルアプリケーションを ダウンロードしてください このセッションで紹介した 全てのコードをご覧いただけます 一通り見ていただき アプリケーションへ プッシュ通知を追加する― スタートとしてご使用ください これらの全てを行うことで アプリケーションに豊かな体験を もたらすことができるでしょう ありがとうございました
-
-
2:02 - Registering for notifications
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { UIApplication.shared.registerForRemoteNotifications() UNUserNotificationCenter.current().delegate = self return true }
-
2:36 - UIApplicationDelegate callbacks
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { // The token is not currently available. print("Remote notification is unavailable: \(error.localizedDescription)") } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { // Forward the token to your provider, using a custom method. self.forwardTokenToServer(token: deviceToken) }
-
3:05 - Forward token to server
func forwardTokenToServer(token: Data) { let tokenComponents = token.map { data in String(format: "%02.2hhx", data) } let deviceTokenString = tokenComponents.joined() let queryItems = [URLQueryItem(name: "deviceToken", value: deviceTokenString)] var urlComps = URLComponents(string: "www.example.com/register")! urlComps.queryItems = queryItems guard let url = urlComps.url else { return } let task = URLSession.shared.dataTask(with: url) { data, response, error in // Handle data } task.resume() }
-
3:47 - Request authorization
@IBAction func subscribeToNotifications(_ sender: Any) { let userNotificationCenter = UNUserNotificationCenter.current() userNotificationCenter.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in print("Permission granted: \(granted)") } }
-
4:43 - Payload JSON
{ "aps" : { "alert" : { "title" : "Check out our new special!", "body" : "Avocado Bacon Burger on sale" }, "sound" : "default", "badge" : 1, }, "special" : "avocado_bacon_burger", "price" : "9.99" }
-
6:11 - didReceive response
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo guard let specialName = userInfo["special"] as? String, let specialPriceString = userInfo["price"] as? String, let specialPrice = Float(specialPriceString) else { // Always call the completion handler when done. completionHandler() return } let item = Item(name: specialName, price: specialPrice) addItemToCart(item) showCartViewController() completionHandler() }
-
8:16 - Register for remote notifications (Background)
class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { UIApplication.shared.registerForRemoteNotifications() return true }
-
9:05 - Background Notification Payload
{ "aps" : { "content-available" : 1 }, "myCustomKey" : "myCustomData" }
-
9:33 - didReceiveRemoteNotification
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { guard let url = URL(string: "www.example.com/todays-menu") else { completionHandler(.failed) return } let task = URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data else { completionHandler(.noData) return } updateMenu(withData: data) completionHandler(.newData) } }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。