在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混编的时 ...
随机推荐
- 901. Online Stock Span [短于线性的时间统计单个元素的Span ]
Span 指这个元素之前连续的小于这个元素的值有多少个 原理: 维护递减栈 这个栈内的元素是递减的序列 新到一个元素x 依次出栈比x小的(也就是这个元素的Span) 这种问题的关键在于 新来的元素如果 ...
- Hadoop 集群规模要多大
- jquery学习:选择器&dom操作
分类; 1.基本选择器 1.标签选择器(元素选择器) * 语法:$("html标签名”) 获得所有匹配标签名称的元素 2.id选择器 * 语法:$("#id的属性值" ...
- Leetcode500.Keyboard Row键盘行
给定一个单词列表,只返回可以使用在键盘同一行的字母打印出来的单词.键盘如下图所示. 示例: 输入: ["Hello", "Alaska", "Dad& ...
- LUOGU P3539 [POI2012]ROZ-Fibonacci Representation
传送门 解题思路 打了个表发现每次x只会被比x大的第一个fab或比x小的第一个fab表示,就直接写了个爆搜骗分,结果过了.. 代码 #include<iostream> #include& ...
- 关系型数据库和nosql非关系型数据库
快下班了.突然和同事聊起了node+mongdb,因为我们这里的项目没有mongdb,就问后端的同事,我们'爱装逼'的后端的同事让我们先自己学习一下什么关系型数据库和非关系型数据库.一顿百度查询了解下 ...
- Firefox Developer Edition - Mozilla
冰狐浏览器开发者工具:https://www.mozilla.org/en-US/firefox/developer/ 冰狐浏览器开发者工具:https://www.mozilla.org/en-US ...
- Codeforces Round #436 (Div. 2) 题解864A 864B 864C 864D 864E 864F
A. Fair Game time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- expect.js
前言 1> 借鉴里面的应用思想,使用断言提高代码的健壮性及维护性 2> 实现方式--不采用直接嵌入expect的方式,统一进行重写(提取常用断言方法,重新构造API) 官网介绍 https ...
- R语言的可视化
1. 完整的数据分析流程 定义研究问题 定义理想数据集 确定能够获取什么数据 清理数据 2. 变量的类型: 数值变量(可进行加减乘除运算):连续(可在给定区间取任意数值).离散(给定集合内不连续取值) ...