[Xcode/Swift] UserNotificationsを知る

iOSアプリで通知機能を実装するには、UserNotificationsフレームワークを使用します。このフレームワークは、ローカル通知やリモートプッシュ通知をスケジュール・管理する機能を提供します。本記事では、UserNotificationsを使った通知の基本的な設定方法から、豊富なサンプルコードを交えて解説します。

UserNotificationsとは?

UserNotificationsフレームワークは、アプリに通知機能を組み込むために使用します。iOSでは、2種類の通知がサポートされています。

  • ローカル通知: アプリ内部でスケジュールされた通知
  • リモート通知: Appleのプッシュ通知サービス(APNs)を介して配信される通知

UserNotificationsの基本設定

通知の許可リクエスト

通知を送信する前に、ユーザーから通知の許可を得る必要があります。アプリの起動時に、以下のコードを使って通知の許可をリクエストします。

import UserNotifications

func requestNotificationPermission() {
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
        if let error = error {
            print("Error requesting notification permission: \(error)")
        }
        
        if granted {
            print("Permission granted")
        } else {
            print("Permission denied")
        }
    }
}

上記のコードでは、alert(バナー表示)、sound(通知音)、badge(アプリアイコンのバッジ)に対してユーザーの許可をリクエストしています。

通知設定の確認

許可のステータスを確認するには、以下のコードを使用します。

center.getNotificationSettings { settings in
    if settings.authorizationStatus == .authorized {
        print("Notifications are authorized")
    } else {
        print("Notifications are not authorized")
    }
}

ローカル通知の実装

通知コンテンツの作成

まず、通知の内容を設定するUNMutableNotificationContentオブジェクトを作成します。

let content = UNMutableNotificationContent()
content.title = "Hello!"
content.body = "This is a local notification"
content.sound = .default
content.badge = 1

通知トリガーの設定

次に、通知をスケジュールするためのトリガーを作成します。ここでは、5秒後に通知を発生させるトリガーを設定します。

let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)

通知リクエストの作成

最後に、UNNotificationRequestオブジェクトを使って、通知リクエストを作成し、通知センターに登録します。

let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
    if let error = error {
        print("Failed to add notification request: \(error)")
    }
}

カスタムアクション付きの通知

通知に対してカスタムアクションを追加することもできます。例えば、「返信」と「削除」アクションを追加してみましょう。

カスタムアクションの作成

まず、アクションを定義します。

let replyAction = UNNotificationAction(identifier: "REPLY_ACTION", title: "Reply", options: [.foreground])
let deleteAction = UNNotificationAction(identifier: "DELETE_ACTION", title: "Delete", options: [.destructive])

カテゴリの作成

次に、アクションを通知に関連付けるためのカテゴリを作成します。

let category = UNNotificationCategory(identifier: "MESSAGE_CATEGORY", actions: [replyAction, deleteAction], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories()

通知にカテゴリを関連付ける

作成したカテゴリを通知コンテンツに設定します。

let content = UNMutableNotificationContent()
content.title = "New message"
content.body = "You have a new message."
content.categoryIdentifier = "MESSAGE_CATEGORY"

通知のカスタマイズ(画像やボタン付き)

通知に画像を追加したり、ボタン付きのインタラクションを提供することが可能です。

画像付き通知

画像を通知に含めるには、UNNotificationAttachmentを使います。

if let imageURL = Bundle.main.url(forResource: "exampleImage", withExtension: "jpg") {
    let attachment = try? UNNotificationAttachment(identifier: UUID().uuidString, url: imageURL, options: nil)
    if let attachment = attachment {
        content.attachments = [attachment]
    }
}

リモートプッシュ通知の準備

リモートプッシュ通知を設定するには、Apple Push Notification Service(APNs)を使用します。ここでは簡単な流れを説明します。

デバイストークンの取得

リモート通知を受信するためには、APNsにデバイストークンを登録する必要があります。

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    print("Device Token: \(token)")
}

通知の登録

アプリの起動時にリモート通知の登録をリクエストします。

UIApplication.shared.registerForRemoteNotifications()

フォアグラウンドでの通知表示

アプリがフォアグラウンドにある場合は通知がデフォルトでは表示されませんが、デリゲートメソッドを使って表示することが可能です。

UNUserNotificationCenter.current().delegate = self

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .sound])
    }
}