应用程序中没有调用方法'application:openURL:options:'。

37

我正在尝试使用自定义 scheme 从网页打开我的应用。应用程序已经打开,但是以下方法没有被调用:

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

我的 info.plist 文件看起来像下面这样:

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

该项目是使用 Xcode 11.1 创建的,并在 iOS 13 上进行测试。


你正在使用iOS13吗? - Dávid Pásztor
是的,它重要吗? - Jabson
2
如果您有一个iOS 13应用程序,那么将调用SceneDelegate方法。 - matt
是的,我会检查并让您知道,请像回答一样发布... - Jabson
是的,请看这个问答:链接 - Dávid Pásztor
请检查我的答案,解决方案是相同的。https://stackoverflow.com/questions/62842100/how-check-data-from-today-widget/64534139#64534139 - LoGoCSE
7个回答

77

在您的场景代理中实现scene(_:openURLContexts:)

如果URL启动您的应用程序,则会收到scene(_:willConnectTo:options:),并且它位于options中。


1
我在想为什么下面的方法没有被调用。application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { - Jitendra
这对我来说是个好建议。谢谢! - Shweta
1
@matt 我只是希望你能在这里提供一段代码片段 :) - Tianyao 'Till' Chen
我的Xcode是最新的,版本号为11.3.1。另一个方法scene(userActivity)被调用时,只有当应用程序在后台运行时才会被调用,但当应用程序不在后台运行时,没有任何方法被调用。 - Asad Ali Choudhry
首先感谢您提供的解决方案。花了一些时间才明白scene(_:openURLContexts:)方法是在应用程序加载并呈现在应用程序堆栈中时调用的。但是,如果应用程序已关闭,符合某种类型并从另一个应用程序调用,则会调用scene(_:willConnectTo:options:)方法而不是openURLContexts方法。 - ETech
显示剩余6条评论

28

这是 SceneDelegate.swift 中的方法。适用于 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)
    }
}

请解释一下"WXApi",并尝试给出一个更通用的例子。 - undefined

24

如果您未使用SceneDelegate,则使用最新的SDK时可以正常工作。

如果您正在使用sceneDelegate,则以下AppDelegate方法不会被调用,因此无法处理登录。

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
}
这是因为这种方法被推迟到SceneDelegate中的以下方法中处理:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    ...
}

我可以确认适用于实现SceneDelegate的iOS 13应用程序的解决方案是:

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])        
}

17

iOS 14 及以上版本可用
用于 SwiftUI 应用程序
注意:此方法处理 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) {

    }
}

1
我已经搜索了好几个小时了。非常感谢!!! - batuhankrbb
当应用程序关闭时,它不起作用,只有在应用程序在后台运行时才有效。在.onOpenUrl中添加DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {...}以解决此问题。 - dibs

5

感谢@Matt的帮助,以下是我是如何解决这个问题的。

在 SceneDelegate.m 文件中:

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
// 获取 URL NSURL *url = connectionOptions.URLContexts.allObjects.firstObject.URL; NSLog(@"当应用程序不在内存中时 ::::: %@",url);
}
​ - (void)scene:(UIScene *)scene openURLContexts:(NSSet *)URLContexts {
// 获取 URL NSURL *url = URLContexts.allObjects.firstObject.URL; NSLog(@"当应用程序在内存中时 ::::: %@",url);
}

我遇到了同样的问题。我已经在这里发布了。你能回答一下吗?https://dev59.com/f1MH5IYBdhLWcg3wnASa - iPhone

2
我遇到了同样的问题,无论是scene(_ scene:, continue userActivity:)还是scene(_ scene:, openURLContexts URLContexts:)都没有被调用。当我检查传递给方法scene(_ scene:, willConnectTo session, options connectionOptions:)connectionOptions时,它包含了一个带有预期URL的用户活动。所以,最终我手动调用了这个方法:
func scene(_ scene: UIScene,
           willConnectTo session: UISceneSession,
           options connectionOptions: UIScene.ConnectionOptions) {

    if let userActivity = connectionOptions.userActivities.first {
        self.scene(scene, continue: userActivity)
    }
}

0

我遇到了一个问题,使用Safari快捷方式启动应用程序时,openURLContexts回调多次。

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>>
)}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接