在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混编的时 ...
随机推荐
- css3之 渐变
CSS3 渐变(gradients)可以让你在两个或多个指定的颜色之间显示平稳的过渡. 以前,你必须使用图像来实现这些效果.但是,通过使用 CSS3 渐变(gradients),你可以减少下载的事件和 ...
- jqGrid列的统计
$("#List").jqGrid({ url: "${pageContext.request.contextPath}/cbfx/getCbhzList.do" ...
- Leetcode199. Binary Tree Right Side View二叉树的右视图
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值. 示例: 输入: [1,2,3,null,5,null,4] 输出: [1, 3, 4] 解释: 先求深度,中 ...
- JavaScript内容梳理 示例之模态对话框 示例之全选和反选以及取消 示例之后台管理左侧菜单
<!DOCTYPE html> <!--示例之模态对话框--> <html lang="en"> <head> <meta c ...
- ObservableCollection类
https://blog.csdn.net/GongchuangSu/article/details/48832721 https://blog.csdn.net/hyman_c/article/de ...
- 超高频率问题之信息: Illegal access: this web application instance has been stopped already. Could not load . The eventual following stack trace is caused by an error thrown for debugging purposes as well as
出现频率非常高,目前还不确定具体是什么原因导致
- Boost.Asio基础
http://www.voidcn.com/article/p-exkmmuyn-po.html http://www.voidcn.com/article/p-xnxiwkrf-po.html ht ...
- System.getProperty()和getenv()
System.getproperty(String name) 获取系统属性 System.getProperties() 获取所有系统属性 System.getenv(String name) 获取 ...
- go struct 工厂
- 注解1 --- JDK内置的三个基本注解 --- 技术搬运工(尚硅谷)
@Override: 限定重写父类方法, 该注解只能用于方法 @Deprecated: 用于表示所修饰的元素(类, 方法等)已过时.通常是因为所修饰的结构危险或存在更好的选择 @SuppressWar ...