【Swift/Apple Watch】ローカル通知機能の実装方法!フォアグラウンド
この記事からわかること
- Swift/Apple Watchアプリでローカル通知を実装する方法
- UNUserNotificationCenterで通知を発行するには?
- フォアグラウンドの際に通知を表示させるには?
- iPhone(iOS)連携アプリでの通知の表示検証
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Xcode:15.0.1
- iOS:17.1
- watchOS:10.1
- Swift:5.9
- macOS:Sonoma 14.1
Apple Watchアプリでローカル通知を実装する方法
watchOSアプリでローカル通知を実装するにはiOS側での実装と同じくUNUserNotificationCenter
を使用します。詳細な実装方法は以下の記事を参考にしてください。
Watch側ではUserNotifications
をimport
しないとUNUserNotificationCenter
クラスが使用できないので注意してください。今回はアプリがフォアグラウンドでも表示されるようにUNUserNotificationCenterDelegate
に準拠させています。
import UserNotifications
class NotificationManager: NSObject, UNUserNotificationCenterDelegate {
static let shared = NotificationManager()
private override init() {
super.init()
// フォアグラウンドでも通知が表示されるようにする
UNUserNotificationCenter.current().delegate = self
requestAuthorization()
}
private func requestAuthorization() {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: .alert) { granted, error in
if granted {
print("許可されました!")
}else{
print("拒否されました...")
}
}
}
func scheduleNotification() {
let content = UNMutableNotificationContent()
content.title = "通知のタイトル"
content.body = "通知の本文"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
let request = UNNotificationRequest(identifier: "uniqueIdentifier", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
// 通知が表示される際に呼ばれるデリゲートメソッド
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .sound, .badge])
}
}
あとはUI側で以下のように組み込めばOKです。
struct ContentView: View {
private let notificationManager = NotificationManager.shared
var body: some View {
Button {
notificationManager.scheduleNotification()
} label: {
Text("Watch Notify")
}
}
}
フィジビリティ
今回はボタン押下後、3秒後に通知が届くように実装しましたが、シミュレーターで動作を確認してみると3秒で届く時もあれば15秒ほどかかる時もある感じで少し不安定な感じでした。
アプリがフォアグラウンドかバックグラウンドの際は上記のような通知ですが、Apple Watch自体がロックされている場合は以下のような通知になります。
もちろん通知をタップするとアプリが起動します。
通知をタップされたことを検知する
通知がタップされてアプリが起動した際に任意の処理を実行したい場合はUNUserNotificationCenterDelegate
の以下のuserNotificationCenter(_:, didReceive : UNNotificationResponse, withCompletionHandler : @escaping () -> Void)
が呼ばれるのでこの中に処理を実装します。
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
print("通知をタップされたよ")
completionHandler()
}
iPhone(iOS)連携アプリの場合の通知の動き
watchOSアプリがiPhoneと連携しているアプリの場合は通知がどこで発行されるかが異なってきます。基本的には連携している場合はiOS側にローカル通知イベントを仕込んでおき、発火させるとiOS側だけでなくWatch側にもリンクして通知が届きます。
シミュレーターで操作確認をしてみましたが、以下のような感じになりました。基本的に設定された通知は連携している両方のOSへ通知されるようです。しかし両方届かない場合はありませんでしたがiOS側が届かなかったり、Watch側が届かなかったりしたのでここら辺は注意が必要かもしれません。
Watch(アクティブ) App:フォアグラウンド |
Watch(アクティブ) App:バックグラウンド |
Watch(非アクティブ) App:バックグラウンド |
|
---|---|---|---|
iOS(アクティブ) App:フォアグラウンド |
両方に通知 | 両方に通知 | 両方に通知 |
iOS(アクティブ) App:バックグラウンド |
両方に通知 | 両方に通知 | 両方に通知 |
iOS(非アクティブ) App:バックグラウンド |
両方に通知 | 両方に通知 | 両方に通知 |
※アクティブはロックされていない状態、非アクティブはデバイスがロックされている状態
色々と調べたり、調査をしてみたところ、通知は基本的にアクティブになっているデバイスに届くと公式に記述されていました。シミュレーターや実機で確認したみた際は上記のような挙動になったのも事実なので不安定な部分が大きいようです。
ご覧いただきありがとうございました。