如何打开我的 SwiftUI 应用程序并使用 Siri Intent Extension 中的 NSUseractivity 执行功能?

How can I open my SwiftUI app and perform a function using NSUseractivity from within Siri Intent Extension?

我的问题

我的应用有自己的使用 Intents Extensions 创建的快捷方式操作。他们完美地执行后台操作。

对于某些操作,我试图让 Intent 扩展程序在 运行 快捷方式中打开主(容器)应用程序并执行一个功能。

我在使用 NSUserActivity 时遇到了问题,我不确定它是一个 SwiftUI 项目还是我实现它的方式(或两者)。

我试过的

我已经在 info.plist ("com.me.project.activityName") 中将我的 NSUserActivity 名称注册为 NSUserActivityType。

我已将以下代码添加到我的 AppDelegate 中。

我在我的意图扩展中初始化了一个新的 NSUserActivity,其类型与 info.plist 中声明的类型相同。

我也试过在应用程序中声明 activity(我认为我不需要这样做?)

我是运行宁: iOS(iPhone XS,测试版 6) macOS 10.15 卡特琳娜(测试版 5) Xcode11.0(测试版 5)

到目前为止我的代码

我的 AppDelegate 中有这个:

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {

          if userActivity.activityType == "com.me.project.activityName" {
              if let url = URL(string: "https://www.google.com") {
                  UIApplication.shared.open(url)
              }
              return true
          }
          return false
      }

这在我的意图扩展中:

let openApp = intent.launchApp?.boolValue ?? false
        if openApp {

            let UA = NSUserActivity(activityType: "com.me.project.activityName")
            UA.title = "Dummy title"

            completion(UserActivityTestIntentResponse(code: .continueInApp, userActivity: UA))

        } else {
            completion(UserActivityTestIntentResponse.success(result: "You chose not to open the app with a user activity."))
        }

在info.plist

<key>NSUserActivityTypes</key>
    <array>
        <string>com.me.project.activityName</string>
    </array>

我在项目的 swift 文件中声明了这个(虽然我认为我不需要它):

let openURLActivityType = "com.me.project.activityName"

let viewPageActivity: NSUserActivity = {
    let userActivity = NSUserActivity(activityType: openURLActivityType)
    userActivity.title = "Dummy Title"
    userActivity.suggestedInvocationPhrase = "Dummy phrase"
    userActivity.isEligibleForSearch = false
    userActivity.isEligibleForPrediction = false
    return userActivity
}()

意外结果

我希望当快捷方式中的操作是 运行 时,我的应用程序会打开并且网站“https://www.google.com”。

目前,在 运行 执行快捷方式中的操作后,我的应用会启动到主屏幕,但没有其他任何反应。我的 appDelegate 中似乎没有断点。

我无法确定是不是因为我错误地使用了 NSUserActivity,是因为它是 SwiftUI 还是它在 intent 内部无法正常工作。

在此先感谢您的帮助!

就像您已经评论过的那样,当应用程序仍在后台时,您可以使用 func scene(_ scene: UIScene, continue userActivity: NSUserActivity) 继续 NSUserActivity

然而,当应用程序关闭时,您可以在 SceneDelegatescene(_:willConnectTo:options:) 方法中实现 let userActvity = connectionOptions.userActivities.first 以访问用户想要继续的 activity。

将这段代码添加到此方法的标准实现中将如下所示:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

    // Use a UIHostingController as window root view controller
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: ContentView())
        self.window = window
        window.makeKeyAndVisible()

        //Standard implementation until here
        if let userActvity = connectionOptions.userActivities.first {
            if let intent = userActivity.interaction?.intent as? YourIntent {
                print(“do something”)
            }
        }
    }
}

这适用于 Swift 5 Xcode 11.

的 Siri Intents

对于 Handoff,尽管 .userActivities 不应如文档所述那样使用,但相关的委托方法将被调用 (scene(_:continue:)):

This property does not contain user activity objects related to Handoff. At connection time, UIKit delivers only the type of a Handoff interaction in the handoffUserActivityType property. Later, it calls additional methods of the delegate to deliver the NSUserActivity object itself.

如果您的应用程序是 SwiftUI 应用程序,也许您应该考虑添加如下内容:

ContentView
   .onContinueUserActivity("com.company.app.activityIdentifier") { userActivity in 
      handleShortcut(with: userActivity)
   }

其中 handleShortcut 正在从给定的 NSUserActivity 获取用户信息,并在打开您的应用程序后启动要完成的操作

这将替换在 func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool 委托方法中所做的任何实现,这些方法不再在您的 SwiftUI 应用程序中调用,除非您编写更多(而不是微不足道的)代码行来调用它

您可以在 :

上找到更多详细信息