4

How do you create an AppIntent that will run in your app's process and use it in your widget's Button? I created a new file, added it to my app's target, created my AppIntent struct, then added a button to my widget: Button(intent: TestIntent()) { Text("Test") }. This results in a compile-time error Cannot find 'TestIntent' in scope which makes sense because this code doesn't exist in the widget extension where I'm trying to use it. But the documentation for adding interactivity to widgets states:

For a widget, create a new structure that adopts the AppIntent protocol and add it to your app target ... In the protocol’s required perform() function, add code for the action you want to make available to the widget.

and

If you adopt the AppIntent protocol, you can add your custom app intent to your widget extension target or your app target. Adding it to the app target is preferable because you can then reuse the button or toggle that you add to your widget in your app.

and

When a person interacts with a button or toggle in your widget, the system runs the perform() function in your app’s process.

Jordan H
  • 52,571
  • 37
  • 201
  • 351

5 Answers5

2

In testing I've been able to determine, at least as of now:

  • If you don't want to reuse the app intent in your app, you only want to use it in your interactive widget, you can add your AppIntent structure to just the widget extension target. With this setup, the intent will always run in the widget process.
  • If you want your app intent to be reusable in your app and your widget, you can add your AppIntent structure to both your app and widget extension targets. With this setup, the intent will run in your app process if your app is running even if suspended in the background, and in the widget process when your app is not running.
  • Despite what the documentation implies, it's seemingly not possible to create a simple AppIntent that will always run in your app's process, unless you implement openAppWhenRun which will cause your app to come to foreground, or you implement a different intent protocol: AudioIntent, LiveActivityIntent, ForegroundContinuableIntent. These intent types run in the app's process in the background.

I submitted FB12584468 to request documentation be updated to explain the requirements and clarify how it works (or fix the bugs if this isn't intended behavior).

And thanks to Michael on Mastodon for clarifying this behavior! "If you need to force an app intent to run in your app and it doesn't match well with any of the paths described ... I’d love to know about it and understand your use case."

Jordan H
  • 52,571
  • 37
  • 201
  • 351
1

I was experiencing the same thing. I'm guessing it's just a bug with the Betas, because it does seem to contradict the documentation.

I found a workaround (as of Xcode beta 5, iOS17 beta 4). If you implement AudioPlaybackIntent instead of AppIntent, then it always launches inside the App's process.

Ben Noland
  • 34,230
  • 18
  • 50
  • 51
0

We can try AppIntentsPackage API

  1. create a MyIntent framework

  2. define a TestIntent

    // MyIntent.framework
    public struct TestIntent: AppIntent {
     static var title: LocalizedStringResource = "xxx"
    
    
     func perform() async throws -> some IntentResult {
         ...
         return .result()
     }
    }
    
    public struct TestIntents: AppIntentsPackage {}
    
  3. import the MyIntent.framework in App or Widget Target.

boog
  • 1,813
  • 3
  • 18
  • 21
0

I found a better solution for interaction Live Activity.

  1. You can create a struct impletion LiveActivityIntent then add it to widget target and app target.
  2. Create two files, one add to widget target, other one add to app target, each extension your Intent and write one same function. Widget target function can empty, app target function is real code. In perform call your function in extensions file.

Above steps make sure compile success and when interaction intent, System will execute your real code in App Process.

iblacksun
  • 11
  • 2
0

As Version 15.0 beta 7, a LiveActivityIntent runs in the main app process as expected.

jeffbailey
  • 137
  • 6