在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
在Swift中检查API的可用性的更多相关文章
- Swift4.0复习特性、编译标志和检查API的可用性
1.Swift中的特性: @引出,后面紧跟特性名,圆括号带参数即可. @attribute(args) avaiable: 指明对象,函数,类型的可用性. @available(iOS 10.0, m ...
- OC Swift中检查代码行数
1 打开终端 cd 进去当前项目 2 总行数查看命令 find . -name "*.m" -or -name "*.h" | xargs wc -l ...
- 在Swift中使用遗留的C API
Swift的类型系统的设计目的在于简化我们的生活,为此它强制用户遵守严格的代码规范来达到这一点.毫无疑问这是一件大好事,它鼓励程序员们编写 更好更正确的代码.然而,当Swift与历史遗留的代码库.特别 ...
- 在Swift中应用Grand Central Dispatch(下)
在第一部分中, 你学到了并发,线程以及GCD的工作原理.通过使用dispatch_barrrier和dispatch_sync,你做到了让 PhotoManager单例在读写照片时是线程安全的.除此之 ...
- 在Swift中应用Grand Central Dispatch(上)转载自的goldenfiredo001的博客
尽管Grand Central Dispatch(GCD)已经存在一段时间了,但并非每个人都知道怎么使用它.这是情有可原的,因为并发很棘手,而且GCD本身基于C的API在 Swift世界中很刺眼. 在 ...
- swift中文文档- 类型转换
未翻译完 待续(英语烂,求斧正) Type Casting 类型转换 Type casting is a way to check the type of an instance, and/or to ...
- 思考 Swift 中的 MirrorType 协议
Swift中的反射非常有限,仅允许以只读方式访问元数据的类型子集.或许 Swift 因有严格的类型检验而不需要反射.编译时已知各种类型,便不再需要进行进一步检查或区分.然后大量的 Cocoa API ...
- Swift与Objective-C API的交互
互用性是让 Swift 和 Objective-C 相接合的一种特性,使你能够在一种语言编写的文件中使用另一种语言.当你准备开始把 Swift 融入到你的开发流程中时,你应该懂得如何利用互用性来重新定 ...
- swift中Any,AnyObject,AnyClass的区别
这几个概念让人很迷惑,看了很多帖子,终于搞明白了,简单总结: Any 和 AnyObject 是 Swift 中两个妥协的产物.什么意思呢,oc中有个id关键字,表示任何对象,oc和swift混编的时 ...
随机推荐
- nodejs+express 初学(三)
Nodejs 的模块,nodejs中每一个js文件都是独立的,不用担心他们中的变量会相互覆盖 模块是 Node.js 应用程序的基本组成部分,文件和模块是一一对应的.换言之,一个Node.js 文件就 ...
- 卸载VS2015之后,安装VS2017出错
安装出现问题. 可通过以下方式排查包故障问题: 1. 使用以下搜索 URL 来搜索针对每个包故障的解决方案 2. 针对受与影响的工作负荷或组件修改选项,然后重新尝试安装 3. 从计算机上删除产品,然后 ...
- LA3905 Meteor
https://vjudge.net/problem/UVALive-3905 计算出每个点在相框中的时间段,扫描线做即可 关键在如何快速计算每个点在相框中的时间段.对每个点进行运动分解,进入的时间L ...
- 支付宝单笔转账demo (改配置直接用)
支付宝接口说明文档 https://docs.open.alipay.com/api_28/alipay.fund.trans.toaccount.transfer 需要注意的是:rsa的 公钥和 ...
- 使用 prerender 实现 SEO
server { listen 80; server_name www.umount.com; access_log /var/log/nginx/livefrontend/access.log LF ...
- svn清理以下路径失败
网上说是svn的数据库挂了 删除里免得数据就好了 用sqllite...嗯? 那我还得下载一个?超过五秒钟的工作我是不会去做的 打开navicat 清空表 再次尝试清理
- python中os模块简介
一.什么是os模块 os模块提供了多数操作系统的功能接口函数.当os模块被导入后,它会自适应于不同的操作系统平台,根据不同的平台进行相应的操作,在python编程时,经常和文件.目录打交道,所以离不了 ...
- MySQL忘记root密码重置密码(5.7版本)
网上找了一堆方法都不行,经过折腾一番,发现MySQL不同版本重置密码也存在一定的差异!记录下Mysql5.7.18版本的重置密码方法. 1.找到/etc/mysql/my.cnf 修改此文件添加一行s ...
- tp5.1 本地正常, 线上route.php不起作用的问题
由于本项目 的.htaccess文件是放在根目录的, 上传没有覆盖,重新编辑 <IfModule mod_rewrite.c> Options +FollowSymlinks -Multi ...
- Django与HTML业务基本结合
app里都有migrations文件 app: migrations 数据修改表结构,数据库操作记录 admin Django为我们提供后台管理 apps 配置当前app models ORM,写指定 ...