从iOS 9开始,第三方应用程序不再能够查询任意URL方案。 几个第三方应用程序(最著名的是Twitter)滥用UIApplication
类的canOpenURL(_:)
方法来跟踪在特定设备上安装了哪些应用程序。
苹果已经制定了一些限制措施来保护其客户的隐私。 在此快速提示中,我将告诉您有关这些更改的知识,并向您展示如何更新应用程序。
1.查询URL方案
我假设您已经知道iOS应用程序可以要求操作系统使用URL方案启动另一个应用程序。 最简单的形式就是这样。
let URLAsString = "tweetbot://_bartjacobs/timeline"
if let URL = NSURL.init(string: URLAsString) {
UIApplication.sharedApplication().openURL(URL)
}
有时,在打开URL之前先询问操作系统是否可以打开URL很有用。 如果要根据用户已安装的应用程序以及您的应用程序可以与之交互的应用程序来更新用户界面,这将特别有用。 在上面的示例中,如果未在用户设备上安装Tweetbot ,则openURL(_:)
将不会成功。 要询问操作系统是否可以打开URL,可以使用UIApplication
类的canOpenURL(_:)
方法。
let URLAsString = "tweetbot://_bartjacobs/timeline"
if let URL = NSURL.init(string: URLAsString) {
if UIApplication.sharedApplication().canOpenURL(URL) {
UIApplication.sharedApplication().openURL(URL)
} else {
print("Cannot Open URL")
}
}
不幸的是,某些应用程序,尤其是Twitter,一直在滥用canOpenURL(_:)
来检测用户设备上安装了哪些应用程序。 据苹果称,这侵犯了用户的隐私。 结果,Apple不再通过施加两个限制来容忍iOS 9中的这种类型的滥用。
- 针对iOS 9 SDK构建的应用程序被迫将要查询的URL方案列入白名单。 换句话说,如果未将URL添加到应用程序的Info.plist中的白名单中,则对
canOpenURL(_:)
的调用将失败。 - 未针对iOS 9 SDK构建的应用程序将继续按预期运行。 但是,有一个限制。 一个应用程序只能查询50个不同的URL方案。 后续请求返回
false
并引发错误。 该文档强调,当用户重新安装或升级该应用程序时,将重置此限制。
2.项目设置
通过创建一个打开我最喜欢的Twitter客户端Tweetbot的简单应用程序,让我向您展示这在实践中意味着什么。 在Xcode 7中创建一个新项目,然后选择“ 单一视图应用程序”模板。 将项目命名为Schemes并将Language设置为Swift 。
在介绍URL方案之前,我想设置用户界面。 打开ViewController.swift并将一个操作openTweetbot(_:)
添加到ViewController
类。 您可以暂时将其实现留空。
// MARK: - Actions
@IBAction func openTweetbot(sender: AnyObject) {
}
打开Main.storyboard并向“ 视图控制器场景”中添加一个按钮。 将按钮的标题设置为Open Tweetbot并将按钮与我们之前创建的视图控制器的openTweetbot(_:)
操作连接。
我们不会使任何事情变得太复杂。 当我点击“ 打开Tweetbot”按钮时,操作系统将打开Tweetbot,向我显示时间轴。 您可以在Tapbots网站上阅读有关Tweetbot URL方案的更多信息。
3.在iOS 9之前
在Apple对查询URL方案施加上述限制之前,您可以执行以下操作:
@IBAction func openTweetbot(sender: AnyObject) {
let application = UIApplication.sharedApplication()
let URLAsString = "tweetbot://_bartjacobs/timeline"
guard let URL = NSURL.init(string: URLAsString) else { return }
guard application.canOpenURL(URL) else { return }
// Open URL
application.openURL(URL)
}
我们询问操作系统是否可以打开传递给canOpenURL(_:)
的URL。 如果此方法在iOS 8及更低版本的iOS 8上返回false
,则假定URL方案与另一个应用程序相关,我们知道我们感兴趣的应用程序未安装在用户的设备上。 这可能非常有用,但是Apple希望对API进行一些限制以避免滥用。
4. iOS 9
如果您使用Xcode 7构建应用程序并点击Open Tweetbot按钮,则canOpenURL(_:)
将返回false
,并且操作系统将引发类似于以下内容的错误:
Schemes[9227:3539016] -canOpenURL: failed for URL: "tweetbot://_bartjacobs/timeline" - error: "This app is not allowed to query for scheme tweetbot"
操作系统明确通知我们,不允许应用程序知道它是否可以打开传递给canOpenURL(_:)
的URL。 但这并不意味着不允许应用程序打开我们传递给openURL(_:)
的URL。
如果您更新如下所示的openTweetbot(_:)
的实现,并且安装了Tweetbot,则在轻击按钮时,应用程序将能够打开Tweetbot。 这强调苹果公司希望限制canOpenURL(_:)
的(mis)使用,而不是openURL(_:)
。
@IBAction func openTweetbot(sender: AnyObject) {
let application = UIApplication.sharedApplication()
let URLAsString = "tweetbot://_bartjacobs/timeline"
guard let URL = NSURL.init(string: URLAsString) else { return }
// Open URL
application.openURL(URL)
}
5.将URL方案列入白名单
幸运的是,这个问题很容易解决。 从iOS 9开始,Apple要求开发人员将应用程序要查询的URL方案列入白名单。 这就像将条目添加到应用程序的Info.plist一样简单。
打开Info.plist ,添加一个名为LSApplicationQueriesSchemes的键,并将值的类型设置为Array 。 将String类型的项添加到数组,并将其值设置为tweetbot 。
如果将openTweetbot(_:)
恢复为其原始实现,则可以调用canOpenURL(_:)
而不会导致操作系统出现错误。 您可以在应用程序的Info.plist中添加尽可能多的URL方案。
@IBAction func openTweetbot(sender: AnyObject) {
let application = UIApplication.sharedApplication()
let URLAsString = "tweetbot://_bartjacobs/timeline"
guard let URL = NSURL.init(string: URLAsString) else { return }
guard application.canOpenURL(URL) else { return }
// Open URL
application.openURL(URL)
}
结论
大多数应用程序不会对Apple的新政策产生任何问题。 显然,Apple旨在通过限制应用程序可以从操作系统中提取的信息来保护其客户的隐私。 应用程序在iOS上使用沙箱,Apple希望控制应用程序可以从沙箱所在的环境中提取多少信息。
将URL方案列入白名单对于大多数应用程序来说并不是很大的麻烦,但是如果您打算创建应用程序启动器(例如Launch Center Pro) ,则可能会变得乏味。 只要将应用程序要查询的每个URL方案列入白名单,仍然可以创建启动器。 但是,这可能非常乏味。
翻译自: https://code.tutsplus.com/tutorials/privacy-and-url-schemes-in-ios-9--cms-26550