環境
- Xcode 11.3
- Swift 5.1.3
- Firebase 6.16.0
- FirebaseDynamicLinks 4.0.7
経緯
「DynamicLinksからアプリを起動した際に、iOS13系でURLをハンドリングできていない」
という問題に最近対応しました。
結局、マルチウィンドウを活用していないことから、SceneDelegateを破棄することで対応しましたが、調べたもの達が可哀想なので供養するために記事にしました。
ちなみにSceneDelegateの破棄対応は3つで完結します。
-
SceneDelegate.swift
を削除 -
info.plist
からApplication Scene Manifest
のkeyを削除 - プロジェクト作成時に
AppDelegate
に自動で組み込まれるfunc application(_:configurationForConnecting:options:)
とfunc application(_:didDiscardSceneSessions:)
を削除
原因
iOS13から UIApplicationDelegate
の func application(_:continue:restorationHandler:)
がDynamicLinksから起動した時に呼び出されなくなっていました。
iOS12以前では前述のメソッドで受け取る userActivity
の webpageURL
を使って下記のようにできるのですが、
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
print(userActivity.webpageURL!)
}
URLは何処へ?
初期対応
UISceneDelegate
でUserActivityを受け取れるメソッドがあるだろうと探したら、ちゃんとありました。
func scene(_:continue:)
(公式ドキュメント)
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
print(userActivity.webpageURL!)
}
良かった、これで一件落着...
と思いきやです
問題
アプリを起動していない時にDyanmicLinksのURLを叩くと先のメソッドが反応しません。
バックグラウンド状態にしておけばちゃんとハンドリングしてくれます。
.....どういうこと
解決策
同じ悩みを抱えていたこちらの方の記事のおかげで解決しました
Handling Firebase Dynamic Links in iOS 13 with Scene Delegate
From connectionOptions we need to get the activity.webpageURL object
おぉ...
どうやらSceneDelegateの func scene(_:willConnectTo:options:)
(公式ドキュメント) に必要な情報が付与されているとのこと。
第3引数に渡されている UIScene.ConnectionOptions
(公式ドキュメント)にはUIKitがsceneを生成する際に、生成された際の情報を紐づけてくれているらしく、その中にUserActivityも含まれていました。
以下のようにしてURLを取り出せます
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
// window生成の記述は省略
guard let userActivity
= connectionOptions.userActivities
.first(where: { $0.webpageURL != nil }) else { return }
print(userActivity.webpageURL!)
}
これで本当の一件落着です。
余談
iPad(iPadOS)ではSafariを開いた際にUserAgentが変わったことが原因か、
そもそもDynamicLinksが機能しない、みたいな問題もありました。
おそらくリンクのparam設定の問題だったのか、こちらの問題はヌルッと解決しました。
ダイナミックリンクURLを手動で構築する