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的可用性的更多相关文章

  1. Swift4.0复习特性、编译标志和检查API的可用性

    1.Swift中的特性: @引出,后面紧跟特性名,圆括号带参数即可. @attribute(args) avaiable: 指明对象,函数,类型的可用性. @available(iOS 10.0, m ...

  2. OC Swift中检查代码行数

    1 打开终端  cd 进去当前项目 2 总行数查看命令     find . -name "*.m" -or -name "*.h" | xargs wc -l ...

  3. 在Swift中使用遗留的C API

    Swift的类型系统的设计目的在于简化我们的生活,为此它强制用户遵守严格的代码规范来达到这一点.毫无疑问这是一件大好事,它鼓励程序员们编写 更好更正确的代码.然而,当Swift与历史遗留的代码库.特别 ...

  4. 在Swift中应用Grand Central Dispatch(下)

    在第一部分中, 你学到了并发,线程以及GCD的工作原理.通过使用dispatch_barrrier和dispatch_sync,你做到了让 PhotoManager单例在读写照片时是线程安全的.除此之 ...

  5. 在Swift中应用Grand Central Dispatch(上)转载自的goldenfiredo001的博客

    尽管Grand Central Dispatch(GCD)已经存在一段时间了,但并非每个人都知道怎么使用它.这是情有可原的,因为并发很棘手,而且GCD本身基于C的API在 Swift世界中很刺眼. 在 ...

  6. swift中文文档- 类型转换

    未翻译完 待续(英语烂,求斧正) Type Casting 类型转换 Type casting is a way to check the type of an instance, and/or to ...

  7. 思考 Swift 中的 MirrorType 协议

    Swift中的反射非常有限,仅允许以只读方式访问元数据的类型子集.或许 Swift 因有严格的类型检验而不需要反射.编译时已知各种类型,便不再需要进行进一步检查或区分.然后大量的 Cocoa API ...

  8. Swift与Objective-C API的交互

    互用性是让 Swift 和 Objective-C 相接合的一种特性,使你能够在一种语言编写的文件中使用另一种语言.当你准备开始把 Swift 融入到你的开发流程中时,你应该懂得如何利用互用性来重新定 ...

  9. swift中Any,AnyObject,AnyClass的区别

    这几个概念让人很迷惑,看了很多帖子,终于搞明白了,简单总结: Any 和 AnyObject 是 Swift 中两个妥协的产物.什么意思呢,oc中有个id关键字,表示任何对象,oc和swift混编的时 ...

随机推荐

  1. Hibernate-HQL-Criteria-查询优化

    1 查询总结 oid查询-get 对象属性导航查询 HQL Criteria 原生SQL 2 查询-HQL语法 2.1 基础语法 2.2 进阶语法 排序 条件 分页 聚合 投影 多表查询 SQL HQ ...

  2. 2019-10-23-C#-从零开始写-SharpDx-应用-绘制基础图形

    title author date CreateTime categories C# 从零开始写 SharpDx 应用 绘制基础图形 lindexi 2019-10-23 21:16:35 +0800 ...

  3. Win10操作系统安装—U盘作为启动盘—系统安装到固态硬盘中

    利用U盘作为启动盘安装win10操作系统 1.U盘制作为启动盘,制作工具,我选择的是大白菜(个人觉得还是很好用的) 大白菜http://www.bigbaicai.com/rjjc/syjc/3269 ...

  4. vue如何发请求

    1.vue 支持开发者引入 jquery 使用 $.ajax() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1.首先,在 package.json 中添加 j ...

  5. MySQL系列(八)--数据库分库分表

    在互联网公司或者一些并发量比较大的项目,虽然有各种项目架构设计.NoSQL.MQ.ES等解决比较高的并发访问,但是对于数据库来说,压力 还是太大,这时候即使数据库架构.表结构.索引等都设计的很好了,但 ...

  6. 前端(jQuery)(5)-- jQuery AJAX异步访问和加载片段

    异步访问 index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset ...

  7. ckfinder图片上传成功,但无法打开This image failed to load.

    原因是basedir和baseurl的问题 本地调试的时候 可以用 这种方式实现,但是部署到线上,就有问题

  8. Django ORM中的查询,删除,更新操作

    ORM查询操作 修改views.py文件 from django.shortcuts import render, HttpResponse from app01 import models from ...

  9. day18 13.乐观锁介绍

    乐观锁是使用版本字段,悲观锁是使用数据库底层的锁机制.mysql的类型timestamp(时间戳)有一个特点:插入数据不用管我,我取系统当前默认值.timestamp插入时间会记录,修改时间也会记录. ...

  10. ZOJ3195 Design the city [2017年6月计划 树上问题04]

    Design the city Time Limit: 1 Second      Memory Limit: 32768 KB Cerror is the mayor of city HangZho ...