[iOS 10] Notification Content app extension を作成して通知 UI にカスタムビューを表示する

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

はじめに

こんにちは。モバイルアプリサービス部の平屋です。

本シリーズ「iOS User Notifications UI framework」では、iOS 10 で新規追加された「User Notifications UI framework」の機能を使用した実装を紹介していきます。

第 1 回目の本記事では「User Notifications UI framework」を使用して「Notification Content app extension」を作成し、通知 UI にカスタムビューを表示する手順を解説します。

目次

User Notifications UI framework

User Notifications UI framework は iOS 10 で新規追加されました。このフレームワークが提供する主な機能は以下の通りです。

  • ローカル通知・リモート通知受信時に表示される UI の見た目をカスタマイズする
  • 「通知が持つデータに対応する視覚表現」を提供するための app extension を定義する
  • app extension をカスタム通知アクションに反応させる

Notification Content app extension

Notification Content app extension は User Notifications UI framework を使用して作成できる app extension です。この app extension を使用すると、システムが提供する通知 UI 上にカスタムビューを表示できます。

user-notifications-ui-framework-0

Notification Content app extension 作成

それでは、Notification Content app extension を作成していきます。

Notification Content app extension の機能を利用するには、既存のアプリに app extension を追加します。app extension を追加すると、必要最低限のコードが自動生成されます。

既存のアプリがない場合は、ここで新規のプロジェクトを作成しちゃいましょう。

app extension を追加する

既存のアプリに Notification Content app extension を追加する手順は以下のとおりです。

  1. Xcode のメニューバーの 「File」 -> 「New」 -> 「Target」 をクリックし、Target 追加用の画面を表示
  2. 「iOS」タブの「Application Extension」グループの中の「Notification Content」を選択して「Next」をクリック
  3. 「Product Name」などを入力し「Finish」をクリック (今回は Product Name を「NotificationContentExtension」とした)
  4. 「Activate "NotificationContentExtension" scheme?」というダイアログが出るので「Activate」をクリック

以上の操作を行うと、app extension 用のターゲットと scheme が作成され、プロジェクトのツリー上の「NotificationContentExtension」グループの中に以下の 3 つのファイルが追加されます。

  • NotificationViewController.swift
  • MainInterface.storyboard
  • Info.plist

app extension 作成時に自動生成されるファイル

app extension 用のターゲット追加時に生成されるファイルをそれぞれ見ていきます。

Info.plist

Info.plist を確認すると NSExtension キーと値が既に設定された状態になっています。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    ...

    <key>NSExtension</key>
    <dict>
        <key>NSExtensionAttributes</key>
        <dict>
            <key>UNNotificationExtensionCategory</key>
            <string>myNotificationCategory</string>
            <key>UNNotificationExtensionInitialContentSizeRatio</key>
            <real>1</real>
        </dict>
        <key>NSExtensionMainStoryboard</key>
        <string>MainInterface</string>
        <key>NSExtensionPointIdentifier</key>
        <string>com.apple.usernotifications.content-extension</string>
    </dict>
</dict>
</plist>

NSExtensionAttributes

このキーの値には、app extension 固有の設定を指定します。

UNNotificationExtensionCategory

通知の「カテゴリ ID」を指定します。初期値は myNotificationCategory です。

UNNotificationExtensionInitialContentSizeRatio

カスタムビューロード中に使用するアスペクト比を指定します。カスタムビューが準備されるまでの間、ここで指定したアスペクト比の白いビューが表示されます。

初期値は 1 なので、高さと幅が同じ長さになります。0.5 を指定すると、高さが幅の半分になります。

NSExtensionMainStoryboard

このキーの値には、app extension のメインの storyboard のファイル名を指定します。

初期値は MainInterface であり、システムが app extension のカスタムビューを使用する場合は「MainInterface.storyboard」ファイルがロードされます。

NSExtensionPointIdentifier

このキーの値には、app extension の種類を識別するための文字列を指定します。ここの値を変更することはないでしょう。

MainInterface.storyboard

この storyboard の内容を確認すると、ViewController 1 つが既に配置された状態になっています。この ViewController にはクラスとして NotificationViewController が割り当てられています。

NotificationViewController.swift

このクラスのデフォルトの実装は以下の通りです。このクラスは UNNotificationContentExtension プロトコルに適合しています。

import UIKit
import UserNotifications
import UserNotificationsUI

class NotificationViewController: UIViewController, UNNotificationContentExtension {

    @IBOutlet var label: UILabel?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any required interface initialization here.
    }

    func didReceive(_ notification: UNNotification) {
        self.label?.text = notification.request.content.body
    }

}

UNNotificationContentExtension プロトコル

このプロトコルは Notification Content app extension のためのエントリーポイントを提供します。

「任意の UIViewController のサブクラス」を当プロトコルに適合させることによって、カスタムビューを提供したり、通知周りのイベントをハンドリングしたりすることができます。

didReceive(_:) メソッド

このメソッドは UNNotificationContentExtension プロトコルで定義されており、カスタムビューが必要になったタイミングで呼ばれます。上記実装では通知の本文をラベルの文字列として設定しています。

動作検証

実装の解説が終わりましたので、Notification Content app extension が提供するカスタムビューの表示を試していきます。

動作検証準備

Notification Content app extension の動作を試す準備として、ローカル通知を作成するためのコードを本体アプリ側に追加します。 追加するコードは以下の (1) 〜 (3) です。

(1) ユーザーの許可を得る

任意のタイミング (アプリ起動時など) で通知の使用許可をリクエストするようにします。

// 通知の使用許可をリクエスト
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { (granted, error) in
    print("granted:\(granted)")
}

(2) カテゴリ ID を作成する

次に、通知のカテゴリを登録する実装を追加します。通知のカテゴリについては、こちらの記事をお読みください。

UNNotificationCategoryidentifier には、app extension の Info.plist に登録してある ID を指定します。

// カテゴリを登録する
let category = UNNotificationCategory(identifier: "myNotificationCategory",
                                      actions: [],
                                      intentIdentifiers: [],
                                      options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])

(3) ローカル通知を作成する

最後に、ローカル通知を作成する実装を追加します。ローカル通知の作成については、こちらの記事をお読みください。

UNMutableNotificationContentcategoryIdentifier プロパティには、手順 (2) で指定したものと同じ ID を指定します。

// ローカル通知を作成する
let content = UNMutableNotificationContent()
content.title = "Hey guys"
content.body = "What's going on here?"
content.categoryIdentifier = "myNotificationCategory"
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 5,
                                                     repeats: false)
let request = UNNotificationRequest.init(identifier: "myNotification",
                                         content: content,
                                         trigger: trigger)
UNUserNotificationCenter.current().add(request)

通知受信時の動作

通知受信時の動作を見ていきます。

通知を受信すると、通常と同じ通知バナーが表示されます。

user-notifications-ui-framework-1

通知バナーをプレス (3D Touch 対応機種の場合) または下方向へドラッグすると、カスタムビューが展開されます。

カスタムビューをロードしている間のアスペクト比は app extension の Info.plist に登録した値になります。

user-notifications-ui-framework-2

カスタムビューのロードが終わると app extension 側で実装した UI が表示されます。MainInterface.storyboard で定義しているレイアウトやカラーが反映されています。

user-notifications-ui-framework-3

さいごに

本記事では「User Notifications UI framework」を使用して「Notification Content app extension」を作成する手順を解説しました。

次回の記事でも引き続き「User Notifications UI framework」の機能について解説していきます。お楽しみに!

参考資料