ControlConfigurationIntent won't open the app despite setting openAppWhenRun = true

I am working on building Control widgets for our app and have noticed that openAppWhenRun doesn't seem to work for any ControlConfigurationIntent. When attaching the debugger to the widget extension in a sample project, I see the following error:

Unknown NSError The operation couldn’t be completed. (LNActionExecutorErrorDomain error 2018.)

This is reproducible as of Xcode 16.0 Beta 2 and Beta 3.

I have noted that using an OpenIntent, with a parameter called target that conforms to AppEnum seems to open the app properly, but if I use that workaround, adding any additional parameters to the OpenIntent seems to break things again.

Are others seeing this issue? I have feedback FB14357691. Here's some sample code below to reproduce:

    var body: some ControlWidgetConfiguration {
        AppIntentControlConfiguration(kind: "Open Any Screen", intent: OpenAppScreenIntent.self) { template in
            ControlWidgetButton(action: template) {
                Label {
                    Text("Open App")
                } icon: {
                    Image(systemName: "calendar")
                }
            }.tint(.red)
        }
    }
}

enum AppScreen: CaseIterable {
    case calendar
    case campus
    case search
    
    var title: String {
        switch self {
        case .calendar:
            "Calendar"
        case .campus:
            "Campus"
        case .search:
            "Search"
        }
    }
}

struct OpenAppScreenIntent: ControlConfigurationIntent {
    
    static var title: LocalizedStringResource = "Open app to a screen"
    static var description = IntentDescription("Opens the app.")

    /// The app should open regardless of what happens here
    static let openAppWhenRun: Bool = true
    
    @Parameter(title: "Screen", optionsProvider: OsuScreenOptionsProvider())
    var screen: String?

    struct OsuScreenOptionsProvider: DynamicOptionsProvider {
        func results() async throws -> ItemCollection<String> {
            
            var screenTitles: [String] = []
            
            for screen in AppScreen.allCases {
                async let title = screen.title
                
                await screenTitles.append(title)
            }
            
            return ItemCollection {
                ItemSection(items: screenTitles.map { IntentItem($0)})
            }
        }
        
        func defaultResult() async -> String? {
            return "Campus"
        }
    }
    
    @MainActor
    func perform() async throws -> some IntentResult {
#warning("The app should open regardless of what happens in this method, but it doesn't")
        return .result()
    }
}
Answered by reed.1325 in 795777022

I have discovered a workaround here:

https://developer.apple.com/forums/thread/758637

It would be nice if we could get an explanation or some diagnostics as to why we need to add our control widgets to the app itself, when they are supposed to reside in an extension or Widget Bundle, since in fact, the Xcode project / target creation tool will put the default Control in an extension target only causing the above code to not work.

Accepted Answer

I have discovered a workaround here:

https://developer.apple.com/forums/thread/758637

It would be nice if we could get an explanation or some diagnostics as to why we need to add our control widgets to the app itself, when they are supposed to reside in an extension or Widget Bundle, since in fact, the Xcode project / target creation tool will put the default Control in an extension target only causing the above code to not work.

I'm unable to get the app to open with OpenIntent, even when my ControlWidgetButton's class is added to both the main app and the extension targets. What code did you use to get that to work?

To see if you can get it working, try putting everything in the same file (ControlConfigurationIntent and your ControlWidget) and then make sure that file is added to your main app target as well as your extension or widget bundle. This most basic code below should work with any ControlWidgetButton and when tapped will open the app.

struct SampleIntent: ControlConfigurationIntent {
    
    static var title: LocalizedStringResource = "Title"
    static var description = IntentDescription("Description.")

    /// Launch your app when the system triggers this intent.
    static let openAppWhenRun: Bool = true
    
    @MainActor
    func perform() async throws -> some IntentResult {

      // You can add more functionality here like a deep link into your app either using a result type that opens a url or write an extension that routes to a screen. 
        return .result()
    }
}

That worked! Do you know which result type opens a URL? I couldn't find one.

You call it like this somewhere in your perform method.

@MainActor
func perform() async throws -> some IntentResult & OpensIntent {
        guard let url = URL(string: "myapp://myappintent") else {
            // throw an error of your choice here
        }

        return .result(opensIntent: OpenURLIntent(deepLink))
    }

More here: https://stackoverflow.com/questions/78716058/ios-18-control-widget-that-opens-a-url

@reed.1325 : I have the same problem, app opens but app delegate is not notified. Reed, do u have a sample app that has this working, would be greatly appreciated !

ControlConfigurationIntent won't open the app despite setting openAppWhenRun = true
 
 
Q