返回

iOS 快捷指令重定向循环问题解析及解决方案

IOS

iOS 快捷指令重定向循环问题解析

在 iOS 开发中,使用快捷指令打开其他应用是一个常见的功能。开发者经常会遇到快捷指令重定向循环的问题,这篇文章将深入探讨这个问题,并提供一些实用解决方案。

问题陷入循环的重定向

想象一下,用户通过你的 App 的快捷指令打开了另一个目标 App(比如 YouTube)。然后,目标 App 又通过某种机制(例如 URL Scheme 或 Universal Link)打开了你的 App。如果你的 App 再次尝试打开目标 App,就会形成一个无限循环,这显然不是我们想要的结果。

用户的预期行为是:

  1. 打开目标 App
  2. 打开你的 App
  3. 再次打开目标 App(此时目标 App 已经在后台)
  4. 不再重定向回你的 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

             }



           }
    
    // 其他处理逻辑...
}

操作步骤:

  1. AppDelegateapplication:continue userActivity:restorationHandler: 方法中处理快捷指令,并调用 handleShortcut 函数。
  2. handleShortcut 函数中,先使用 UIApplication.shared.canOpenURL(_:) 方法检查目标 App 是否已安装。
  3. 如果已安装,再检查应用状态 (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")
}

操作步骤:

  1. 定义一个 UserDefaults 键值,例如 "hasOpenedTargetApp"。
  2. 在快捷指令的 perform 函数中,检查该键值是否为 true
  3. 如果为 false,则打开目标 App 并将该键值设为 true
  4. AppDelegateapplicationDidBecomeActive(_:) 方法中,将该键值重置为 false

额外的安全建议

在处理 URL Schemes 和 Universal Links 时,务必验证链接的来源,以防止潜在的安全风险。 就像检查来访客人的身份一样,确保他们是友好的,而不是恶意闯入者。

更多资源

这些解决方案对你有帮助吗?你还有其他更好的建议吗?欢迎分享你的经验和想法! 希望这篇文章能帮助你解决 iOS 快捷指令重定向循环的问题。