标签:
指责Swift是“没有C的Objective-C”的说法不够准确,是因为Swift和Objective-C缺少相似之处,而不是没有C。Swift根本不是类C语言。
毫无疑问Swift从Haskell、Rust、Python、D语言等现代编程语言里获得灵感,但你最好把它理解成拒绝了C语言中一些坏掉地方的语言:
甚至可以说Swift类型系统的设计,是因为对C++类型系统的不满发泄而来的。
在Objective-C里,检查API的可用性是通过C语言预处理指令来完成的,在class, respondsToSelector:以及instancesRespondToSelector:上的条件式为:
1
2
3
4
5
6
|
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 if ([NSURLSession class] && [NSURLSessionConfiguration respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]) { // ... } #endif |
然而,就像之前提到的,Swift的编译器指令是非常强约束的,只允许针对特定操作系统和平台来做编译器标记和条件式编辑。
1
2
3
|
#if DEBUG println( "OTHER_SWIFT_FLAGS = -D DEBUG" ) #endif |
相应函数和对应的有效参数分别为:
OS():OSX, iOS
arch():x86_64, arm, arm64, i386
1
2
3
4
5
|
#if os(iOS) var image: UIImage? #elseif os(OSX) var image: NSImage? #endif |
不幸的是,os()不提供特定版本的OS X和iOS的深度信息,表明检查发生在运行时。并且由于Swift对处理nil的不太宽容,对Objective-C风格的常量进行检查会导致程序崩溃。
那么,你应该如何检查Swift中的系统信息来确定API的可用性呢?下面我们就来谈谈。
NSProcessInfo
预 料到开发者对检查系统版本同时又对Swift友好的API的需求,iOS 8在NSProcessInfo中引入了operatingSystemVersion属性和 isOperatingSystemAtLeastVersion方法。两个API都使用了新的NSOperatingSystemVersion数值类 型,它包括majorVersion、minorVersion和patchVersion。
Tips:苹果软件发布的版本号遵循语义化版本约定。
isOperatingSystemAtLeastVersion
对一个简单的检查,比如“这个app能在iOS 8运行吗?” isOperatingSystemAtLeastVersion是最简单明了的方式。
1
2
3
4
5
|
if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 8, minorVersion: 0, patchVersion: 0)) { println( "iOS >= 8.0.0" ) } |
operatingSystemVersion
为了更复杂的版本比较,operatingSystemVersion能够被直接检查。将它和Swift模式比较和switch语句组合,可以使得代码更简洁。
1
2
3
4
5
6
7
8
9
10
11
|
let os = NSProcessInfo().operatingSystemVersion switch (os.majorVersion, os.minorVersion, os.patchVersion) { case (8, _, _): println( "iOS >= 8.0.0" ) case (7, 0, _): println( "iOS >= 7.0.0, < 7.1.0" ) case (7, _, _): println( "iOS >= 7.1.0, < 8.0.0" ) default : println( "iOS < 7.0.0" ) } |
UIDevice systemVersion
可惜的是,新NSProcessInfo API目前并不是特别有用,因为它们在iOS 7上不生效。
作为替代,可以使用systemVersion属性UIDevice来进行检查:
1
2
3
4
5
6
|
switch UIDevice.currentDevice().systemVersion.compare( "8.0.0" , options: NSStringCompareOptions.NumericSearch) { case .OrderedSame, .OrderedDescending: println( "iOS >= 8.0" ) case .OrderedAscending: println( "iOS < 8.0" ) } |
Tips:当比较版本号字符串时,使用NSStringCompareOptions.NumericSearch来确定大小的比较,比如”2.5″ < “2.10”。
字符串比较和NSComparisonResult不如特定的数值类型如NSOperatingSystemVersion好用,不过它们的功能是一样的。
NSAppKitVersionNumber
另 一个确定API可用性的方法是检查框架的版本号。不幸的是,Foundation的NSFoundationVersionNumber和Core Foundation的kCFCoreFoundationVersionNumber很早之前就过时了,但过去几个版本的OS发布并没有更新这两个常 量。
这对于iOS来说是无解的,但OS X还可以通过NSAppKitVersionNumber检查AppKit的版本号:
1
2
3
|
if rint(NSAppKitVersionNumber) > NSAppKitVersionNumber10_9 { println( "OS X >= 10.10" ) } |
Tips:苹果在示例代码中使用rint来完成NSAppKitVersionNumber的版本号比较。
将以上的总结一下,在Swift中检查系统版本总共有以下方法。
· 使用#if os(iOS)预编译指令来区别iOS(UIKit)和OS X(AppKit)目标。
· 当最低目标适配为iOS 8以上时,使用NSProcessInfo operatingSystemVersion 或isOperatingSystemAtLeastVersion。
· 如需适配iOS 7或以下的设备,使用UIDevice systemVersion上的compare和 NSStringCompareOptions.NumericSearch。
· 如果是为OS X开发,使用NSAppKitVersionNumber比较生效的AppKit常量。
标签:
原文地址:http://www.cnblogs.com/iCocos/p/4535870.html