Method 'application:openURL:options:' is not called
Asked Answered
J

7

38

I'm trying to open my app from a web page using custom schemes. The app is opened but the following method is not called:

func application(_ app: UIApplication, open url: URL, options [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    // This is not called
}

My info.plist looks like the following:

    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>MyApp</string>
            </array>
            <key>CFBundleURLName</key>
            <string>url here</string>
        </dict>
    </array>

The project is created with Xcode 11.1, and I'm testing on iOS 13.

Jaal answered 30/10, 2019 at 11:53 Comment(6)
Are you on iOS13?Restraint
yeap. does it matter?Jaal
If you have an iOS 13 app it’s the SceneDelegate methods that are called.Rooftop
yes i do... i will check and let u know, please post like an answer...Jaal
Yes, have a look at this Q&ARestraint
Check my answer on this question the solution is same. #62842600Halfbound
R
77

Implement scene(_:openURLContexts:) in your scene delegate.

If the URL launches your app, you will get scene(_:willConnectTo:options:) instead and it’s in the options.

Rooftop answered 30/10, 2019 at 12:30 Comment(11)
I was wondering why below method was not called. application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {Trenttrento
Can you answer this? #58973643Anticlinorium
This was the tip for me. Thanks!Provolone
Could you elaborate how to achieve it in scene(_:willConnectTo:options:)? Thanks.Dilan
@Rooftop I was just hoping maybe you could provide a code snippet here:)Dilan
In my case none of these methods are being called, neither scene(:openURLContexts:) nor scene(:willConnectTo:options:).Graphomotor
@AsadAliChoudhry With a project created before Xcode 11, they would not be.Rooftop
my xcode is latest, 11.3.1. The other method scene( userActivity) is calling but only when app is in background, but when its not in background none of the methods is calling.Graphomotor
Will every active scene be called or does the OS just pick one?Bascomb
What if I'm currently working in Xcode 10. Does that mean openURL willnot be called at all in iOS 13+ ??Linguist
Thanks for the solution first of all. It took time to understand that scene(_:openURLContexts:) called when the app is loaded and presented in apps stack. But if the app IS CLOSED, conforms to some type and called from another app, scene(_:willConnectTo:options:) is being called instead of openURLContexts method.Shane
T
28

Here is the method in SceneDelegate.swift. Swift version For iOS13

@available(iOS 13.0, *)
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    if let url = URLContexts.first?.url {
        // Handle URL
        WXApi.handleOpen(url, delegate: AppDelegate.shared)
    }
}
Trenttrento answered 16/11, 2019 at 13:25 Comment(2)
please explain "WXApi" and try to give a more generic example.Vidicon
WXApi here is Wechat API to Open the url in WeChatTrenttrento
C
25

With the latest SDK, this does work fine if you are at NOT using SceneDelegate.

If you are using sceneDelegate the the following AppDelegate method is not called and therefore the login cannot be handled.

func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    let handled = ApplicationDelegate.shared.application(
        application,
        open: url,
        sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
        annotation: options[UIApplication.OpenURLOptionsKey.annotation])
    return handled
}

This is because, this method is (understandably) deferred to the following method in the SceneDelegate:

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    ...
}

The solution which I can confirm as working for iOS 13 applications implementing a SceneDelegate is:

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let url = URLContexts.first?.url else {
        return
    }
    let _ = ApplicationDelegate.shared.application(
        UIApplication.shared,
        open: url,
        sourceApplication: nil,
        annotation: [UIApplication.OpenURLOptionsKey.annotation])        
}
Caerleon answered 29/11, 2019 at 1:35 Comment(0)
B
22

iOS 14 and above
For SwiftUI apps
Note: This method handles the reception of Universal Links
public func onOpenURL(perform action: @escaping (URL) -> ()) -> some View

@main
MyApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            RootView()
                .onOpenURL(perform: handleURL)
        }
    }

    func handleURL(_ url: URL) {

    }
}
Bromide answered 14/11, 2020 at 19:51 Comment(2)
I've been searching for this for hours. Thank you so much!!!!Lacielacing
It is not worked when app is closed, only if app is in background. Add DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {...} inside .onOpenUrl to fix thisEpiphany
S
5

Thanks to @Matt there This is how I solve the problem.

on SceneDelegate.m

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {

    NSURL *url = connectionOptions.URLContexts.allObjects.firstObject.URL;
    NSLog(@"When app is not on memory  ::::: %@",url);

}

​
- (void)scene:(UIScene *)scene openURLContexts:(NSSet *)URLContexts {

    NSURL *url = URLContexts.allObjects.firstObject.URL;    
    NSLog(@"When app is on memory ::::: %@",url);

}
Sungsungari answered 31/10, 2019 at 7:52 Comment(1)
I am facing same issue. I have posted here. Could you answer it? #58973643Anticlinorium
H
2

I had the same problem, and neither scene(_ scene:, continue userActivity:) nor scene(_ scene:, openURLContexts URLContexts:) was called.

When I checked the connectionOptions passed to the method scene(_ scene:, willConnectTo session, options connectionOptions:) it had a user activity with the expected URL. So, I ended up calling the method manually:

func scene(_ scene: UIScene,
           willConnectTo session: UISceneSession,
           options connectionOptions: UIScene.ConnectionOptions) {

    if let userActivity = connectionOptions.userActivities.first {
        self.scene(scene, continue: userActivity)
    }
}
Harpole answered 17/12, 2019 at 9:13 Comment(0)
C
0

I encountered a problem, using safari shortcut to start the application, openURLContexts callback multiple times.

2019-12-09 18:33:41.257088+0800 OCTEST[5019:1468254] openURLContextsopenURLContexts {(
    <UIOpenURLContext: 0x2805a71c0; URL: appoctest://action=123123123; options: <UISceneOpenURLOptions: 0x280bd4750; sourceApp: (null); annotation: (null); openInPlace: NO>>
)}
2019-12-09 18:33:42.022132+0800 OCTEST[5019:1468254] openURLContextsopenURLContexts {(
    <UIOpenURLContext: 0x2805a6d40; URL: appoctest://action=123123123; options: <UISceneOpenURLOptions: 0x280bd6f70; sourceApp: (null); annotation: (null); openInPlace: NO>>
)}
Crackle answered 9/12, 2019 at 11:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.