[iOS 10] User Notifications framework を使用して「カスタム通知アクション付の通知」をカスタマイズする #wwdc

2016.07.13

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは。モバイルアプリサービス部の平屋です。前回の記事に引き続き、iOS 10 で追加された「User Notifications framework」のクラスを使用した実装を紹介します。

本記事では、「カスタム通知アクション付の通知」の表示や挙動をカスタマイズする方法を紹介します。

「カスタム通知アクション付のローカル通知」の作成方法はこちらの記事で、「カスタム通知アクション付のリモート通知」の作成方法についてはこちらの記事で解説しました。これらの記事で説明を省略した「通知のカスタマイズ方法」について解説していきます。

本記事は Apple からベータ版として公開されているドキュメントを情報源としています。 そのため、正式版と異なる情報になる可能性があります。ご留意の上、お読みください。

検証環境

  • Xcode Version 8.0 beta 2 (8S162m)
  • iPhone 6s
    • iOS 10.0 (14A5297c)

UNNotificationAction の 引数 options について

以前の記事で説明を省略した UNNotificationAction の引数 options について解説していきます。

UNNotificationAction を作成する際に、引数 optionsUNNotificationActionOptions をセットすると、カスタム通知アクションの表示や挙動をカスタマイズすることができます。

UNNotificationActionOptions には以下の 3 つの値が用意されています。

  • UNNotificationActionOptions
    • authenticationRequired
    • destructive
    • foreground

authenticationRequired を指定すると、ユーザーが通知に応答した時にデバイスがロックされていた場合、ロックを解除しないとアクションを選択できないようになります。

destructive を指定すると、通知 UI 上に表示されるアクション用のボタンのテキストカラーが赤色になります。このオプションは、アクションが破壊的な処理の場合に使用します。

foreground を指定すると、ユーザーがアクションを選択した時にアプリがフォアグラウンドで起動するようになります。また、このオプションを指定すると、authenticationRequired を指定した場合と同様に、デバイスのロックを解除しないとアクションを選択できないようになります。

アクションのオプションを指定する

アプリ内のアイテムを削除する「Delete」アクションのように、「破壊的」かつ「デバイスのロック解除が必要」なアクションの場合は、以下のように destructiveauthenticationRequiredを指定します。

let delete = UNNotificationAction(identifier:"deleteActionIdentifier",
                                  title:"Delete",
                                  options:[.destructive, .authenticationRequired])

メッセージアプリにおける「Reply」アクションのように、アプリをフォアグラウンドで起動してユーザーとのやり取りを行う必要があるアクションの場合は、以下のように foreground を指定します。

let foreground = UNNotificationAction(identifier:"replyActionIdentifier",
                                      title:"Reply",
                                      options:[.foreground])

UNNotificationCategory の 引数 intentIdentifiers と options について

以前の記事で説明を省略した UNNotificationCategory の引数 intentIdentifiersoptions について解説していきます。

intentIdentifiers について

Siri のリクエストに関連する通知のためにカテゴリを作る場合、カテゴリ作成時に intent (ユーザーの意図を表現するオブジェクト) の ID を指定できるようです。

let category = UNNotificationCategory(identifier: "message",
                                      actions: [action],
                                      minimalActions: [action],
                                      intentIdentifiers: ["intentIdentifier"],
                                      options: [.customDismissAction])

options について

続いて、引数 options について解説していきます。

引数 options にセットできる UNNotificationCategoryOptions には以下の 2 つの値が用意されています。

  • options: UNNotificationCategoryOptions
    • customDismissAction
    • allowInCarPlay

customDismissAction を指定すると、通知を削除した時のイベントをハンドリングすることができるようになります。

また、allowInCarPlay を指定すると、CarPlay 環境で通知を表示することができるようになります。

通知を削除した時のイベントをハンドリングする

通知を削除した時のイベントをハンドリングする実装は以下のようになります。

カテゴリ作成時に customDismissAction を指定します。

let category = UNNotificationCategory(identifier: "message",
                                      actions: [action, delete, foreground, textInputAction],
                                      minimalActions: [action, textInputAction],
                                      intentIdentifiers: [],
                                      options: [.customDismissAction])

そして、userNotificationCenter(_:didReceive:withCompletionHandler:) メソッドを実装します。

システムが提供する通知 UI 上の「Dismiss」または「Clear」または「x」ボタンを押すことで、通知を削除するアクションを実行できます。このアクションが実行されたタイミングで、前述したメソッドが呼ばれます。また、これらのボタンが押された場合の actionIdentifierUNNotificationDismissActionIdentifier になります。

// 任意のオブジェクトを UNUserNotificationCenter のデリゲートにする
UNUserNotificationCenter.current().delegate = self
func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: () -> Void) {

    // DismissAction かどうかを判別
    if response.actionIdentifier == UNNotificationDismissActionIdentifier {
        print("Dismiss Action")
    }

    ...

    // 処理完了時に呼ぶ
    completionHandler()
}

テキスト入力可能なアクションについて

以前の記事で紹介した「カスタム通知アクション」に対してユーザーが行うことが出来る操作はボタンをタップすることだけでしたが、テキスト入力可能なアクションを作成することもできます。

テキスト入力可能なアクションを作成する

テキスト入力可能なアクションを作成するには、UNNotificationAction ではなく、そのサブクラスである UNTextInputNotificationAction を作成します。identifiertitleoptions に指定する値は、UNNotificationAction の場合と同じです。

ユーザーが「テキスト入力可能な Action」を選択すると、通知 UI 上にテキストフィールドと送信ボタンが表示されます。 textInputButtonTitle に指定した文字列が送信ボタンのタイトルになり、textInputPlaceholder に指定した文字列がテキストフィールドのプレースホルダ文字列になります。

// UNTextInputNotificationAction を作成する
let textInputAction = UNTextInputNotificationAction(identifier: "textInput",
                                                    title: "TextInput",
                                                    options:[],
                                                    textInputButtonTitle: "Send",
                                                    textInputPlaceholder: "Enter Text")

入力されたテキストを取得する

ユーザーがテキスト入力用の UI を使用してテキストを送信したイベントは、他のアクションと同様に UNUserNotificationCenterDelegateuserNotificationCenter(_:didReceive:withCompletionHandler:) メソッドを実装することによってハンドリングできます。

テキスト入力が行われた場合、response 引数の型が UNTextInputNotificationResponse になり、このオブジェクトからテキストを取り出すことができます。

// 任意のオブジェクトを UNUserNotificationCenter のデリゲートにする
UNUserNotificationCenter.current().delegate = self
func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: () -> Void) {
    // 入力されたテキストを取得する
    if let textInputResponse = response as? UNTextInputNotificationResponse {
        print("userText:\(textInputResponse.userText)")
    }

    ...

    // 処理完了時に呼ぶ
    completionHandler()
}

さいごに

本記事では「カスタム通知アクション付の通知」をカスタマイズする実装を紹介しました。

通知の表示や挙動をカスタマイズする際の参考になれば幸いです!

参考資料