在Swift中检查API的可用性
http://www.cocoachina.com/swift/20150901/13283.html
本文由CocoaChina译者ALEX吴浩文翻译自Use Your Loaf博客
原文:Checking API Availability With Swift
Swift 2改进了检查API可用性的方法,使其更加容易、安全。
回顾Objective-C的方法
在看Swift之前,让我们简要回顾一下我们之前用Objective-C检查SDK可用性的方法。
检查类和框架的可用性
iOS 9作为一个重要的版本,引进了许多新的框架。但如果你部署版本低于iOS 9,你需要弱连接(weak link)这些新框架,然后在运行时检查其类的可用性。例如:如果我们想在iOS 9中使用新的联系人框架(Contacts framework),而在iOS 8中使用旧的通讯录框架(AddressBook framework):
1
2
3
4
5
6
|
if ([CNContactStore class]) { CNContactStore *store = [CNContactStore new ]; //... } else { // 使用旧框架 } |
检查方法的可用性
用respondsToSelector检查框架内是否含有此方法。例如:iOS 9在Core Location框架中新增了allowsBackgroundLocationUpdates属性:
1
2
3
4
5
|
CLLocationManager *manager = [CLLocationManager new ]; if ([manager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) { // 在iOS 8中不可用 manager.allowsBackgroundLocationUpdates = YES; } |
陷阱
这些方法既难以维护,又没有看上去那么安全。也许某个API现在是公有的,但在早期的版本中却有可能是私有的。例如:iOS 9中新增了几个文本样式,如UIFontTextStyleCallout。如果只想在iOS 9中使用这种样式,你可以检查其是否存在,因为它在iOS 8中应该是null的:
1
2
3
|
if (UIFontTextStyleCallout) { textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleCallout]; } |
不幸的是结果并非如此。原来这个标志在iOS 8中是存在的,只是没有宣布公有。使用一个私有的方法或值有可能出现难以预料的结果,况且这也和我们的想法不同。
Swift 2的方法
Swift 2内置了可用性检查,而且是在编译时进行检查。这意味着当我们使用当前部署版本不可用的API时,Xcode能够通知我们。例如:如果我在部署版本为iOS 8的情况下使用CNContactStore,Xcode将提出以下改进:
1
2
3
4
5
|
if #available(iOS 9.0, *) { let store = CNContactStore() } else { // 旧版本的情况 } |
同样这可以取代我们之前使用的respondsToSelector:
1
2
3
4
|
let manager = CLLocationManager() if #available(iOS 9.0, *) { manager.allowsBackgroundLocationUpdates = true } |
可用性检查的使用情形
#available条件适用于一系列平台(iOS, OSX, watchOS) 和版本号。例如:对于只在iOS 9或OS X 10.10上运行的代码:
1
2
3
|
if #available(iOS 9, OSX 10.10, *) { // 将在iOS 9或OS X 10.10上执行的代码 } |
即使你的App并没有部署在其他平台,最后也需要用*通配符来包括它们。
如果某块代码只在特定的平台版本下执行,你可以用guard声明配合#available来提前return,这样可以增强可读性:
1
2
3
4
5
6
7
8
|
private func somethingNew() { guard #available(iOS 9, *) else { return } // 在iOS 9中执行的代码 let store = CNContactStore() let predicate = CNContact.predicateForContactsMatchingName( "Zakroff" ) let keys = [CNContactGivenNameKey, CNContactFamilyNameKey] ... } |
如果整个方法或类只在特定的平台版本下存在,用@available:
1
2
3
4
5
|
@available(iOS 9.0, *) private func checkContact() { let store = CNContactStore() // ... } |
编译时的安全性检查
结束前,让我们再看看那个常量在iOS 9中公有却在iOS 8中私有的问题。如果部署版本为iOS 8,我们却把字体设置为一个只有iOS 9才能用的样式,这将产生一个编译错误:
1
2
|
label.font = UIFont.preferredFontForTextStyle(UIFontTextStyleCallout) > 'UIFontTextStyleCallout' is only available on iOS 9.0 or newer |
Swift使其便于调试,同时能够根据平台版本赋一个合理的值:
1
2
3
4
5
|
if #available(iOS 9.0, *) { label.font = UIFont.preferredFontForTextStyle(UIFontTextStyleCallout) } else { label.font = UIFont.preferredFontForTextStyle(UIFontTextStyleBody) } |
阅读推荐:
WWDC 2015 Session 403 Improving Your Existing Apps with Swift
WWDC 2015 Session 411 Swift in Practise
最新文章
- 51nod 1237 最大公约数之和 V3
- EC笔记,第一部分:1.视C++为一个语言联邦
- 关于NOIP2016与NOI2018
- 8-Highcharts曲线图之对数直线图
- 【编程题目】一串首尾相连的珠子(m 个),有 N 种颜色(N<;=10),取出其中一段,要求包含所有 N 中颜色,并使长度最短。
- oracle 配置
- CDOJ 486 Good Morning 傻逼题
- sql截取数据库数字字段内容
- ui的设计原则
- jni 入门 android的C编程之旅 --->;环境搭建&;&;helloworld
- swift3 控件创建
- 37.看下图实现如下接口和类,并完成Adventure中的主方法。
- 利刃 MVVMLight 4:绑定和绑定的各种使用场景
- GD库知识点
- 如何用Python写一个计算器软件 附带效果图
- CentOS中安装配置Nginx
- 使用java命令重启tomcat
- CentOS, FreeBSD, Ubuntu LTS 维护风格的简单比较
- python_01
- hive 一次更新多个分区的数据
热门文章
- 时序数据库连载系列: 时序数据库一哥InfluxDB之存储机制解析
- agc033
- Opencv中的阈值函数
- Django项目:CRM(客户关系管理系统)--27--19PerfectCRM实现King_admin数据修改
- 通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账号--锁定次数--菜单功能&#39;menufile
- 实现一个函数clone,使JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制
- 20190813「Night」-Blind
- springmvc 使用了登录拦截器之后静态资源还是会被拦截的处理办法
- invalid use of null value
- 快速乘O(1)和O(log)