如何解决与 AppDelegate 和 SceneDelegate 的深层链接
我正在尝试实现深层链接以导航到应用上的帖子,这是一个较旧的项目,因此我不得不添加 SceneDelegate
类。深层链接实现仅在应用程序处于活动状态或在后台时有效。如果应用程序尚未加载,深层链接将不起作用。我看过很多关于这个的帖子和教程,但没有找到原因,有没有人遇到过类似的问题?
在 AppDelegate
类中,我添加了处理以下函数链接的实现:
func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {}
func application(_ app: UIApplication,open url: URL,options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {}
func application(_ application: UIApplication,continue userActivity: NSUserActivity,restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {}
func application(_ application: UIApplication,sourceApplication: String?,annotation: Any) -> Bool {}
在 SceneDelegate
中,我实现了以下函数中的链接处理:
func scene(_ scene: UIScene,willConnectTo session: UIScenesession,options connectionoptions: UIScene.Connectionoptions) {}
func scene(_ scene: UIScene,openURLContexts URLContexts: Set<UIOpenURLContext>) {}
func scene(_ scene: UIScene,continue userActivity: NSUserActivity) {}
这些函数的实现如下所示:
let navigator = Navigator()
navigator.getDesination(for: url)
func getDesination(for url: URL){
let destination = Destination(for: url)
let ivc = InstantiateViewController()
switch destination {
case .post(let postID):
ivc.openPostVC(id: postID,showComment: true,commentID: nil)
case .user(let userID):
ivc.openProfileVC(userID: userID)
default:
break
}
}
enum Destination {
case post(Int)
case user(Int)
case Feed(String)
case store
case safari
init(for url: URL){
if(url.pathComponents[1] == "p"){
self = .post(Int(url.pathComponents[2])!)
} else if(url.pathComponents[1] == "user") {
self = .user(Int(url.pathComponents[2])!)
} else if(url.pathComponents[1] == "store") {
self = .store
} else if(url.pathComponents[1] == "s") {
self = .Feed(url.pathComponents[2])
} else {
self = .safari
}
}
}
func openProfileVC(userID: Int){
let service = UserPool.shared.request(for: userID)
let storyboard = UIStoryboard(name: "Profile",bundle: nil)
let profileVC = storyboard.instantiateViewController(withIdentifier: "ProfileView") as! ProfileViewController
profileVC.userService = service
profileVC.shouldNavigatetoHome = true
profileVC.shouldNavigatetoHomeAction = {
self.loadMainStoryboard()
}
let navigationVC = UINavigationController(rootViewController: profileVC)
navigationVC.view.backgroundColor = .white
if #available(iOS 13.0,*) {
guard let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate else {return}
sceneDelegate.window?.rootViewController = navigationVC
sceneDelegate.window?.makeKeyAndVisible()
} else {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
appDelegate.window?.rootViewController = navigationVC
appDelegate.window?.makeKeyAndVisible()
}
}
网站 app-site-association 文件如下所示,并在 Xcode 中添加了关联域:
{"applinks":{"apps":[],"details":[{"appID":"{my ID}","paths":["*"]}]},"webcredentials":{"apps":["{my ID}"]}}
解决方法
在带有场景委托的 iOS 13 及更高版本中,您的应用可以在启动时观察传入的通用链接事件,如下所示:
func scene(_ scene: UIScene,willConnectTo session: UISceneSession,options connectionOptions: UIScene.ConnectionOptions) {
if let url = connectionOptions.userActivities.first?.webpageURL {
// ... or might have to cycle thru multiple activities
}
}
如果应用程序已经在运行,你可以使用这个:
func scene(_ scene: UIScene,continue userActivity: NSUserActivity) {
if let url = userActivity.webpageURL {
// ...
}
}
(我有一个非常简单的 downloadable demo app,它证明这确实有效。我不明白它无效的说法;也许问题在于不了解如何测试。)>
,我没有找到答案,所以我决定解决这个问题。我只恢复到 AppDelegate
,在这种情况下,深度链接仅在应用处于活动状态或在后台时才有效。为了解决这个问题,我决定将 URL 存储在 UserDefaults
中。所以在 didFinishLaunchingWithOptions
函数中,我添加了以下内容:
if let url = launchOptions?[UIApplication.LaunchOptionsKey.url] as? URL {
UserDefaults.setURLToContinue(urlString: url.absoluteString)
} else if let activityDictionary = launchOptions?[UIApplication.LaunchOptionsKey.userActivityDictionary] as? [AnyHashable: Any] {
for key in activityDictionary.keys {
if let userActivity = activityDictionary[key] as? NSUserActivity {
if let url = userActivity.webpageURL {
UserDefaults.setURLToContinue(urlString: url.absoluteString)
}
}
}
}
这是我创建的 UserDefaults
扩展:
extension UserDefaults {
class func setURLToContinue(urlString: String){
UserDefaults.standard.set(urlString,forKey: "continueURL")
}
class func getURLToContinue() -> String? {
return UserDefaults.standard.string(forKey: "continueURL")
}
class func removeURLToContinue(){
UserDefaults.standard.removeObject(forKey: "continueURL")
}
}
最后在初始视图控制器的 viewDidLoad
函数中我处理链接:
if let urlString = UserDefaults.standard.string(forKey: "continueURL") {
let url = URL(string: urlString)!
let navigator = Navigator()
navigator.getDesination(for: url)
UserDefaults.removeURLToContinue()
}
Navigator
类决定在导航堆栈上推送哪个视图控制器
此后一切正常
,class SceneDelegate: UIResponder,UIWindowSceneDelegate {
//---------
//-------
func scene(_ scene: UIScene,openURLContexts URLContexts: Set<UIOpenURLContext>) {
for context in URLContexts {
print("url: \(context.url.absoluteURL)")
print("scheme: \(context.url.scheme)")
print("host: \(context.url.host)")
print("path: \(context.url.path)")
print("components: \(context.url.pathComponents)")
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。