何时可以在通用链接中使用SFSafariViewController、WKWebView或UIWebView?

23
在iOS应用搜索编程指南的iOS App Search Programming GuideUniversal Links部分中,苹果表示:
如果您实例化SFSafariViewController、WKWebView或UIWebView对象来处理通用链接,则iOS会在Safari中打开您的网站,而不是打开您的应用程序。但是,如果用户从嵌入的SFSafariViewController、WKWebView或UIWebView对象中点击通用链接,则iOS会打开您的应用程序。
什么是“处理通用链接”?我是否不能使用SFSafariViewControllerWKWebViewUIWebView打开给定的URL?它只适用于-[UIApplicationDelegate application:continueUserActivity:restorationHandler:]期间吗?还是有一个时间限制?这是否意味着我们不能在SFSafariViewControllerWKWebViewUIWebView中打开该URL?
2个回答

9
我不确定我完全理解你的问题。
为了基本覆盖,我将允许苹果解释什么是通用链接what a Universal Link is:
通用链接允许用户在WKWebView和UIWebView视图以及Safari页面中点击指向您网站的链接时打开您的应用程序,除此之外,还包括导致调用openURL:的链接,例如在邮件、消息和其他应用程序中出现的链接。
所以基本上,想象一下你正在使用Twitter客户端,并浏览时间轴,你遇到了一个带有以下YouTube视频链接的推文:https://youtu.be/ejQod8liXm0 如果你点击它,由于它是HTTP URL,你会期望Safari打开链接。然而,我认为我们所有的iOS开发者都可以基本上同意一个事实,即原生应用程序更好,因此更好的用户体验将是官方YouTube应用程序打开视频,即使是从第三方客户端。
这就是“通用链接”的作用;如果YouTube应用在iOS上注册自己作为处理https://www.youtube.com(*)链接的应用程序,如果我们遵循API规则,那么iOS生态系统中的每个人都会受益。如果您运行一个网站并希望任何内容都可以触发官方iOS应用程序打开,如果用户已安装该应用程序,则会提示用户是否安装它以获得更好的用户体验(当然也有助于您的业务)。

那么,现在回到原始文本:

如果您实例化SFSafariViewController、WKWebView或UIWebView对象来处理通用链接,则iOS会在Safari中打开您的网站,而不是打开您的应用程序。但是,如果用户从嵌入式SFSafariViewController、WKWebView或UIWebView对象中点击通用链接,则iOS将打开您的应用程序。

这意味着,如果您的应用程序中的用户通过通用链接(例如:http://www.your-company.com/foo)点击访问您的内容,并且您没有通过正则表达式等方式在应用程序代码中检测到它,而是实例化了SFSafariViewControllerWKWebViewUIWebView将其打开,就像打开The New York Times或其他常规链接一样,操作系统将理解您希望Safari为您处理它,而不是在您的应用程序中打开它。请记住:通用链接的整个目的是让用户通过本地应用程序处理URL,而不是通过浏览器处理,以获得更好的体验。

第一句话是说这个意思。至于第二句话,它澄清了一个可能的后续问题:如果用户从另一个不属于我的应用程序的嵌入式浏览器中点击通用链接访问我的内容怎么办?那么,该句子说,操作系统将正常运行:它将打开您的应用程序,遵循通用链接规则。

TL;DR: 你需要在代码中检测应用程序到你的内容的通用链接,并处理它们。iOS不会为你处理这个问题。相反,如果你告诉操作系统从你的应用程序中的嵌入式浏览器打开一个通用链接到你的应用程序的内容,它将按照指示执行。
编辑:如果你需要帮助决定使用 SFSafariViewController 还是 -openURL:options:completitionHandler: API来打开URL,this link should help you;我的建议是首先使用 -openURL:options:completitionHandler:,如果不成功,则使用SFSafariViewController或类似的API。
希望这有所帮助,也希望我正确理解了你的问题。
干杯!祝您 iOS 11 编程愉快! :)

1
如果您点击它,由于它是一个HTTP URL,您会期望Safari打开链接。如果YouTube链接在普通的UITableViewCell中,我必须以某种方式“处理”YouTube链接,可以使用-[UIApplication openURL:options:completionHandler:]或者使用UIWebViewWKWebViewSFSafariViewController。我假设如果我使用Web视图来“处理”YouTube链接,系统不会打开YouTube应用程序,但-openURL:options:completionHandler:会打开。如何知道该做哪个? - Heath Borders
2
以下链接提供了你所寻找的答案,我想:https://useyourloaf.com/blog/openurl-deprecated-in-ios10/这个想法是,你可以首先使用-openURL:options:completitionHandler:,如果不成功(**成功的布尔值为false**),你可以使用SFSafariViewController或类似的东西。 - dinesharjani
2
请更新您的回答,直接包含此内容,我将标记您为正确。谢谢! - Heath Borders
1
@HeathBorders 完成了! - dinesharjani

4

我用下面的Swift 4类解决了这个问题。如果可能,它还使用了嵌入式Safari浏览器。你也可以在你的情况下按照类似的方法操作。

import UIKit
import SafariServices

class OpenLink {
    static func inAnyNativeWay(url: URL, dontPreferEmbeddedBrowser: Bool = false) { // OPEN AS UNIVERSAL LINK IF EXISTS else : EMBEDDED or EXTERNAL
        if #available(iOS 10.0, *) {
            // Try to open with owner universal link app
            UIApplication.shared.open(url, options: [UIApplication.OpenExternalURLOptionsKey.universalLinksOnly : true]) { (success) in
                if !success {
                    if dontPreferEmbeddedBrowser {
                        withRegularWay(url: url)
                    } else {
                        inAnyNativeBrowser(url: url)
                    }
                }
            }
        } else {
            if dontPreferEmbeddedBrowser {
                withRegularWay(url: url)
            } else {
                inAnyNativeBrowser(url: url)
            }
        }
    }
    private static func isItOkayToOpenUrlInSafariController(url: URL) -> Bool {
        return url.host != nil && (url.scheme == "http" || url.scheme == "https") //url.host!.contains("twitter.com") == false
    }
    static func inAnyNativeBrowser(url: URL) { // EMBEDDED or EXTERNAL BROWSER
        if isItOkayToOpenUrlInSafariController(url: url) {
            inEmbeddedSafariController(url: url)
        } else {
            withRegularWay(url: url)
        }
    }
    static func inEmbeddedSafariController(url: URL) { // EMBEDDED BROWSER ONLY
        let vc = SFSafariViewController(url: url, entersReaderIfAvailable: false)
        if #available(iOS 11.0, *) {
            vc.dismissButtonStyle = SFSafariViewController.DismissButtonStyle.close
        }
        mainViewControllerReference.present(vc, animated: true)
    }
    static func withRegularWay(url: URL) { // EXTERNAL BROWSER ONLY
        if #available(iOS 10.0, *) {
            UIApplication.shared.open(url, options: [UIApplication.OpenExternalURLOptionsKey(rawValue: "no"):"options"]) { (good) in
                if !good {
                    Logger.log(text: "There is no application on your device to open this link.")
                }
            }
        } else {
            UIApplication.shared.openURL(url)
        }
    }
}

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