zoukankan      html  css  js  c++  java
  • 在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

  • 相关阅读:
    前沿技术解密——VirtualDOM
    Ques核心思想——CSS Namespace
    Unix Pipes to Javascript Pipes
    Road to the future——伪MVVM库Q.js
    聊聊CSS postproccessors
    【译】十款性能最佳的压缩算法
    Kafka Streams开发入门(9)
    Kafka Streams开发入门(8)
    【译】Kafka Producer Sticky Partitioner
    【译】99th Percentile Latency at Scale with Apache Kafka
  • 原文地址:https://www.cnblogs.com/itlover2013/p/4777464.html
Copyright © 2011-2022 走看看