返回
iOS 快捷指令重定向循环问题解析及解决方案
IOS
2024-11-01 18:28:10
iOS 快捷指令重定向循环问题解析
在 iOS 开发中,使用快捷指令打开其他应用是一个常见的功能。开发者经常会遇到快捷指令重定向循环的问题,这篇文章将深入探讨这个问题,并提供一些实用解决方案。
问题陷入循环的重定向
想象一下,用户通过你的 App 的快捷指令打开了另一个目标 App(比如 YouTube)。然后,目标 App 又通过某种机制(例如 URL Scheme 或 Universal Link)打开了你的 App。如果你的 App 再次尝试打开目标 App,就会形成一个无限循环,这显然不是我们想要的结果。
用户的预期行为是:
- 打开目标 App
- 打开你的 App
- 再次打开目标 App(此时目标 App 已经在后台)
- 不再重定向回你的 App ,因为你的 App 已经在后台运行。
循环产生的原因:重复的逻辑
这个问题的核心在于 App 和目标 App 之间的跳转逻辑出现了重复。你的 App 在每次启动时都无条件地尝试打开目标 App,而没有考虑到目标 App 的状态。 就像一个过度热情的迎宾员,不停地把客人引进同一个房间。
解决方案一:检查 App 状态
一个简单的解决方案是在你的 App 启动时检查目标 App 是否已经在后台运行。如果已经在后台,就不要再次尝试打开它。 这就像迎宾员确认客人是否已经在房间里一样。
代码示例:
import UIKit
func handleShortcut(appName: String, bundleID: String, deepLinking:String) {
let appIsActive = UIApplication.shared.canOpenURL(URL(string: "\(deepLinking)")!) // 检查是否可通过URL Schemes或Universal Links打开App
let application: UIApplication = .shared
let secondAppPath: String = bundleID
let isRunningSecondApp: Bool = UIApplication.shared.canOpenURL(URL(string:"\(secondAppPath)//")!) ? application.open(URL(string:"\(secondAppPath)//")!) : false
// if target is active
let targetPath: String = deepLinking
if !isRunningSecondApp
{
print("app is not active")
UIApplication.shared.open(URL(string:"\(targetPath)")!)
}
if application.applicationState == .active
{
print("app is active or background \(application.applicationState) \(appName)")
if (!appIsActive){
NotificationCenter.default.post(name: Notification.Name(rawValue: "show_secondAppInstalledOrNotPopup"), object: nil,userInfo: ["data":"\(appName)","isDeepLinkActive":false])
}
else
{
UIApplication.shared.open(URL(string:"\(targetPath)")!)
// 这里发送通知
}
// do smth
}
if application.applicationState == .background {
// 这里什么也不做
// let _: Bool = application.open(URL(string:"\(targetPath)")!)
print("App is active background case \(application.applicationState)")
NotificationCenter.default.post(name: Notification.Name(rawValue: "show_secondAppInstalledOrNotPopup"), object: nil,userInfo: ["data":"\(appName)","isDeepLinkActive":true])
}
if application.applicationState == .inactive {
if application.open(URL(string:"\(targetPath)")!)
{
// show second installed or not popup
print("App is in inactive case \(application.applicationState)")
// do smth
}
}
// 其他处理逻辑...
}
操作步骤:
- 在
AppDelegate
的application:continue userActivity:restorationHandler:
方法中处理快捷指令,并调用handleShortcut
函数。 - 在
handleShortcut
函数中,先使用UIApplication.shared.canOpenURL(_:)
方法检查目标 App 是否已安装。 - 如果已安装,再检查应用状态 (
UIApplication.shared.applicationState
)。如果应用处于非活动状态(.inactive
),打开目标应用,否则,什么都不做。
解决方案二:使用用户默认值(UserDefaults)
另一种方法是使用 UserDefaults
记录是否已经打开过目标 App。在你的 App 启动时,检查这个标志位。如果已经打开过,就不再重复打开。 这个方法就像在门上贴个便条,提醒自己已经进去过一样。
代码示例:
import UIKit
// ... (其他代码) ...
func perform() async throws -> some IntentResult {
// ... (其他代码) ...
let defaults = UserDefaults.standard
let hasOpenedTargetApp = defaults.bool(forKey: "hasOpenedTargetApp")
if !hasOpenedTargetApp {
// 打开目标 App 的逻辑
UIApplication.shared.open(URL(string:"\(targetPath)")!)
defaults.set(true, forKey: "hasOpenedTargetApp")
}
return .result()
}
// 在 AppDelegate 的 applicationDidBecomeActive(_:) 方法中重置标志位
func applicationDidBecomeActive(_ application: UIApplication) {
UserDefaults.standard.set(false, forKey: "hasOpenedTargetApp")
}
操作步骤:
- 定义一个
UserDefaults
键值,例如 "hasOpenedTargetApp"。 - 在快捷指令的
perform
函数中,检查该键值是否为true
。 - 如果为
false
,则打开目标 App 并将该键值设为true
。 - 在
AppDelegate
的applicationDidBecomeActive(_:)
方法中,将该键值重置为false
。
额外的安全建议
在处理 URL Schemes 和 Universal Links 时,务必验证链接的来源,以防止潜在的安全风险。 就像检查来访客人的身份一样,确保他们是友好的,而不是恶意闯入者。
更多资源
这些解决方案对你有帮助吗?你还有其他更好的建议吗?欢迎分享你的经验和想法! 希望这篇文章能帮助你解决 iOS 快捷指令重定向循环的问题。