在Swift中检查API的可用性

15 篇文章 0 订阅

本文由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

 

感谢:

http://www.cocoachina.com/swift/20150901/13283.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值