Question

iOS 18 Control Widget that opens a URL

I already have an iOS 17 App Intent that works with a URL:

@available(iOS 16, *)
struct MyAppIntent: AppIntent {
    static let title : LocalizedStringResource = "My App Inent"
    static let openAppWhenRun   : Bool = true
    
    @MainActor
    func perform() async throws -> some IntentResult{
        await UIApplication.shared.open(URL(string: "myapp://myappintent")!)
        return .result()
    }
}

Now, with iOS 18 and Control Widgets, I want to create a Control Widget button that simply opens the app with the same URL. However, UIApplication code is not allowed within extensions. For this, Apple says to use OpenIntent which is shown here:

Documentation Link

Apple Sample Code from the link:

import AppIntents

struct LaunchAppIntent: OpenIntent {
    static var title: LocalizedStringResource = "Launch App"
    @Parameter(title: "Target")
    var target: LaunchAppEnum
}


enum LaunchAppEnum: String, AppEnum {
    case timer
    case history


    static var typeDisplayRepresentation = TypeDisplayRepresentation("Productivity Timer's app screens")
    static var caseDisplayRepresentations = [
        LaunchAppEnum.timer : DisplayRepresentation("Timer"),
        LaunchAppEnum.history : DisplayRepresentation("History")
    ]
}

WWDC session video about this does not cover this particular method in detail and also this sample code is a bit confusing.

So how can I alter this code to just open the app with a URL?

 2  277  2
1 Jan 1970

Solution

 3

I'm making use of the OpenURLIntent, and it's working perfectly.

@available(iOS 18.0, watchOS 11.0, macOS 15.0, visionOS 2.0, *)
struct MyIntent: AppIntent {
    static let title: LocalizedStringResource = "My Intent"
    static var openAppWhenRun: Bool = true

    init() {}

    @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))
    }
}
2024-07-16
podomunro

Solution

 1

You just need to setup your ControlWidget first and then link your OpenIntent.

Something like:

struct OpenAppnButton: ControlWidget {
    var body: some ControlWidgetConfiguration {
        
        StaticControlConfiguration(
            kind: "your_id"
        ) {
            ControlWidgetButton(action: LaunchAppIntent()) { // <-- HERE
                Label("Something, image: "arrow.up")
            }
        }
        .displayName("Open app")
    }
}
2024-07-15
StefanLdhl

Solution

 0

is possibile to show a custom view from a widget control intent?

func perform() async throws -> some ProvidesDialog & ShowsSnippetView {
    .result(
        dialog: "title",
        view: CustomView()
    )
}
2024-07-22
Fast