Open specific screen in App Delegate after iOS 18 Control Center widget is tapped (failed to open URL)

I have created an iOS 18 Control Center Widget that launches my app. However I am not able to detect it in AppDelegate.swift. I have created custom scheme funRun://beginRun in Target => Info => URL Types URL Types setup in Xcode

This method in AppDelegate.swift does not fire at all and I get this error in console:

Failed to open URL runFun://beginRun: Error Domain=NSOSStatusErrorDomain Code=-10814 "(null)" UserInfo={_LSLine=279, _LSFunction=-[_LSDOpenClient openURL:fileHandle:options:completionHandler:]}``
`
 func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
// this does not fire
        print("Scheme \(url.scheme)")
        print("Host \(url.host)")
        return true
    }`

I tried this answer to no avail: iOS 18 Control Widget that opens a URL

Even adding EnvironmentValues().openURL(url) as suggested here did not help.


 @MainActor
    func perform() async throws -> some IntentResult & OpensIntent {
        let url = URL(string: "funRun://beginRun")!
        EnvironmentValues().openURL(url)
        return .result(opensIntent: OpenURLIntent(url))
    }

Here is my extension code: My goal is to detect the url string from the request, so I can decide which screen to launch from AppDelegate's open url method. When I test this with iOS 18 RC it does not work either in simulator or on real device


import AppIntents
import SwiftUI
import WidgetKit

@available(iOS 18.0, watchOS 11.0, macOS 15.0, visionOS 2.0, *)
struct StartRunControl: ControlWidget {
    var body: some ControlWidgetConfiguration { 
                                               
        StaticControlConfiguration(
            kind: "name.funRun.StartRun",
            provider: Provider()
        ) { value in
                ControlWidgetButton("Hello",
                                    action: MyIntent()) { hi in
                    Label("Start", systemImage: "sun.min.fill")
                }
        }
        .displayName("Start run")
        .description("Opens a run screen.")
    }
}
 
@available(iOS 18.0, watchOS 11.0, macOS 15.0, visionOS 2.0, *)
extension StartRunControl {
    struct Provider: ControlValueProvider {
        var previewValue: Bool {
            false
        }

        func currentValue() async throws -> Bool {
            let isRunning = true // Check if the timer is running
            return isRunning
        }
    }
}

@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 {
        let url = URL(string: "funRun://beginRun")!
        EnvironmentValues().openURL(url)
        return .result(opensIntent: OpenURLIntent(url))
    }
}

I even checked info.plist and it seems okay.


    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLName</key>
            <string>beginRun</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>funRun://beginRun</string>
            </array>
        </dict>
    </array>

Does anyone know where the problem might be? Thanks!

I think it's failing because you setup your URL scheme in the editor to a bad format.

Follow this closely and try using that first. You just setup the scheme and you can parse the query property in the app delegate method.

https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app

You have your control setup correctly to open the url, but the answer on this Stack is also helpful for parsing and adding query items. You can add that bit of code in your intent / app delegate for parsing and formulating the URL:

https://stackoverflow.com/questions/73418995/open-url-scheme-through-widget-tap-ios-16-widget-kit

Open specific screen in App Delegate after iOS 18 Control Center widget is tapped (failed to open URL)
 
 
Q