1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SwiftUI】通知をタップして起動したときのデバッグ方法

Posted at

はじめに

ある日、自分が作ったアプリにプッシュ通知を実装してテストしていたときのこと。
「通知をタップしたら特定の画面を開く」ようにしたはずなのに、なぜか思った通りに動いてくれない…。

しかもアプリがバックグラウンドにあるときは正常に動くのに、未起動状態から通知をタップした場合だけ挙動がおかしい。
ログを見ようにも、通常のビルド起動では再現できず、原因の切り分けに苦労しました。

同じように悩んでいる方のために、この記事では 「通知をタップしてアプリを起動したときの挙動をデバッグする方法」 をまとめます。
特にSwiftUIプロジェクトを例に、Xcodeの設定やprintログを使った観察手順を解説していきます。

手順

1. スキームを「通知起動」向けに設定する

まずはXcodeのスキーム設定を変えて、通知経由でアプリが起動したときにデバッガをアタッチできるようにします。

  1. Xcode上部のスキーム選択
  2. Edit Scheme… をクリック
  3. 左ペインで Run(Debug) を選択
  4. Info タブを開く
  5. Launch 項目の Automatically から Wait for executable to be launched に変更
  6. Closeで閉じる
  7. [▶︎](Run)ボタンを押すと、Xcodeが 「Waiting to attach…」 状態になります
  8. この状態で通知を受け取り
    → タップすると、アプリが起動し即座にデバッガがアタッチされます

スクリーンショット1 スクリーンショット2
スクリーンショット3

2. SwiftUI + AppDelegateでprint()を仕込む

SwiftUIプロジェクトの場合でも、通知ハンドリングは AppDelegateを組み込む のが一般的です。

import SwiftUI
import UserNotifications

@main
struct NotificationDebugApp: App {
    // AppDelegateをSwiftUIに統合
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    
    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        // 通知起動時のLaunchOptionsを確認
        print("[DEBUG] didFinishLaunchingWithOptions:", launchOptions ?? [:])
        
        UNUserNotificationCenter.current().delegate = self
        application.registerForRemoteNotifications()
        return true
    }
    
    // 通知タップ後に必ず呼ばれる
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        print("[DEBUG] didReceiveNotificationResponse:", response.notification.request.content.userInfo)
        completionHandler()
    }
}

3. 実際のprintログ例

例えば、通知をタップしてアプリを起動したときに以下のようなログがデバッグエリアに出力されます。

●未起動状態時(didFinishLaunchingWithOptions

[DEBUG] didFinishLaunchingWithOptions: [AnyHashable("UIApplicationLaunchOptionsRemoteNotificationKey"): {
    aps = {
        alert =     {
            body = "新着メッセージがあります";
            title = "チャット";
        };
        sound = default;
    };
    roomId = 12345;
}]

launchOptions の中に UIApplicationLaunchOptionsRemoteNotificationKey が含まれていて、通知payloadがそのまま渡されていることが分かります。

●通知タップ後(userNotificationCenter(_:didReceive:…)

[DEBUG] didReceiveNotificationResponse: {
    aps = {
        alert =     {
            body = "新着メッセージがあります";
            title = "チャット";
        };
        sound = default;
    };
    roomId = 12345;
}

userInfo に同じpayloadが入っていて、タップ後はこちらのメソッドが必ず呼ばれることが確認できます。

まとめ

今回の記事では、通知をタップして未起動状態からアプリを立ち上げたときの挙動をデバッグする方法を整理しました。

  • スキームを「待機モード」にして通知起動を再現
  • SwiftUIでもAppDelegateを組み込み、didFinishLaunchingWithOptionsuserNotificationCenter(_:didReceive:…)print()を仕込む
  • 実際のログを見て launchOptionsuserInfo の中身を比較することで、どのタイミングでどんなデータが来ているか把握できる

未起動状態時の挙動を理解できると、通知ハンドリングの不具合調査や動作確認がスムーズになります。
「通知タップでうまく動かない…」と悩んでいる方は、ぜひ試してみてください!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?