♪ Xcode中版本相关的配置项
1. Base SDK
- 简单来说它表示的是Xcode可以支持的最高版本,即app能支持的最高版本。
- 在
Target的build setting
中能找到这个配置项,指的是当前编译所用的SDK版本,它会引导编译器使用该版本的SDK进行编译和构建应用。 - 只有你使用的类或者方法、属性在Base SDK中不存在,才会编译错误。那些被标记为
弃用
的旧API依然是可以编译通过的,不过会提供编译警告。如果实际运行的设备SDK版本太低,没有对应的新的类或方法、属性,app就会crash!
2. Deployment Target
-
表示app支持的最低iOS版本。
-
如果app支持的最低版本是iOS 8,则iOS 7的设备上,App Store会自动阻止用户安装或者升级到该app版本。
-
目前除了大厂用户量大,需要支持到iOS 7,其他普通app支持到iOS 8就差不多了。
3. 在Xcode 8以上适配iOS 7
记得当我终于找到iOS 7的设备,兴奋ヾ(o◕∀◕)ノヾ地连到Xcode上的时候,居然弹窗报错Could not loacte device support files
,excuse me???原来Xcode 8开始,默认最低支持的iOS版本为iOS 8,你可以在Deployment Target
的列表中看到,app最低只能支持到iOS 8。
既然app最低只能支持到iOS 8,那就连iOS 8下的bebug都无法调试了。具体解决方法:iOS开发-Xcode8兼容iOS7手记
一些需要掌握的知识:
-
Xcode是通过什么来兼容iOS版本
在路径
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport
下,能够看到Xcode支持的iOS版本。现在这里的版本只从8.0开始,所以我们要把需要的配置包放进来。这样之后,我们就能用iOS 7的设备调试程序了。
-
让
Deployment Target
的列表中出现iOS 7的选项在导入对应版本的配置包之后,的确可以调试了,但是
Deployment Target
的列表中依然不能支持到iOS 7。在
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk
下的SDKSettings.plist
,做相应的一些修改,这个问题也就解决了。
♪ 编译时检查SDK版本,运行时检查系统版本
1. 编译时检查SDK版本
1.1 系统预设的宏定义
-
表示系统版本的宏
文件路径:
usr/include/Availablity.h
,只截取了一小部分,本机的SDK只支持到__IPHONE_10_2
#define __IPHONE_8_0 80000
#define __IPHONE_8_1 80100
#define __IPHONE_8_2 80200
#define __IPHONE_8_3 80300
#define __IPHONE_8_4 80400
#define __IPHONE_9_0 90000
#define __IPHONE_9_1 90100
#define __IPHONE_9_2 90200
#define __IPHONE_9_3 90300
#define __IPHONE_10_0 100000
#define __IPHONE_10_1 100100
#define __IPHONE_10_2 100200
/* __IPHONE_NA is not defined to a value but is uses as a token by macros to indicate that the API is unavailable */
-
app支持的最低和最高版本
文件路径:
usr/include/AvailabilityInternal.h
-
__IPHONE_OS_VERSION_MIN_REQUIRED
相当于Deployment Target
的配置,表示app支持运行的最低版本。 -
__IPHONE_OS_VERSION_MAX_ALLOWED
相当于Base SDK
的配置,表示app支持的最高版本。
-
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
/* make sure a default max version is set */
#ifndef __IPHONE_OS_VERSION_MAX_ALLOWED
#define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_10_2
#endif
...
#endif
1.2 在编译时检测SDK版本
-
在编译阶段,利用条件编译,决定要打包的代码。接下来无论使用什么系统,这个条件判断再也没有用处了。
-
利用
__IPHONE_OS_VERSION_MIN_REQUIRED
检查是否仍然需要支持某些旧版本的功能。
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0
//minimum deployment target is 8.0, so it’s safe to use iOS 8-only code 当前SDK最小支持的设备系统,即8.0,所以在iOS 8.0设备上是安全的
#else
//you can use iOS8 APIs, but the code will need to be backwards //compatible or it will crash when run on an iOS 7 device 你仍然可以使用iOS 8的API,但是在iOS 7的设备上可能会crash. #endif
- 利用
__IPHONE_OS_VERSION_MAX_ALLOWE
检查是否开始使用新的功能。
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
//you can use iOS 10 APIs here because the SDK supports them //but the code may still crash if run on an iOS 8 device 可以使用最新的iOS 10的API,开始支持的新功能。但是仍然可能会在iOS 8的设备上crash。
#else
//this code can’t use iOS 10 APIs as the SDK version doesn’t support them 不能使用iOS 10的API,只能使用iOS 10之前的。 #endif
- 也可以通过检查一个表示版本的宏是否存在来判断,现在最高能支持的版本号。
#ifdef __IPHONE_10_0
// 如果预定义了__IPHONE_10_0这个宏,表示最高支持的版本在10.0以上,包括10.1
#endif
// 除此之外类似的用法还有
#ifdef NSFoundationVersionNumber_iOS_7_1
// 如果NSFoundation的版本在7.1之上,包括7.1
#endif
2. 运行时检查系统版本
2.1 UIDevice
-
通过获取当前设备的系统版本号
[[UIDevice currentDevice] systemVersion]
,返回值为NSString
类型。 -
可以将上面返回的字符串类型转换成浮点型进行比较,这样效率会比比较字符串高,但是由于浮点型的精度问题,可能会出现小版本号匹配错误的问题。
-
可以直接比较当前设备系统版本号的字符串,这个精度当然会比转换成浮点型后比较的高。
[[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame
2.2 判断NSFoudation或者CFCoreFoudation版本号
- 类似于iOS系统版本宏,
NSFoudation
和CFCoreFoudation
两个框架每个版本号也有对应的宏,这两个框架的版本号是随着iOS系统版本号更新的。 - 可以通过
NSFoundationVersionNumber
和kCFCoreFoundationVersionNumber
这两个常量获取当前SDK下NSFoudation
和CFCoreFoudation
的版本号,都是double
类型。 -
CoreFoudation
的版本号定义在文件CoreFoundatin/CFBase.h
中。 -
NSFoudation
的版本号定义在Foundation/NSObjRuntime.h
中。 - 可以在运行中通过获得
NSFoundationVersionNumber
或者kCFCoreFoundationVersionNumber
的值,来判断当前的版本。 - 这种方法的判断,精度并不准确,对于不同的小版本号,可能会出现不同的系统版本会存在相同的值。
♪ iOS 8新API NSProcessInfo
♪ 高效地进行版本判断
- 编译时能做的判断就放在编译期,减少运行时的开销
- 在精度可以忽略的时候,浮点型判断的开销最低,其次使用字符串的版本判断。
- 对低版本的判断先放前面,因为低版本的iOS往往意味着设备的性能较差,这样在低版本的iOS上就可以最先进入应该执行的代码块。当然,低版本的iOS往往也意味着用户量比较少。
♪ 其他一些跟版本相关的宏
1. weakly linked 弱连接(有NS_CLASS_AVAILABLE标示的类)
- 在判断某个类是否存在时,除了通过系统版本号,还可以直接访问指定类名是否存在,有两种方式:
// 普通的判断方式
Class class = NSClassFromString (@"UIAlertController");
if (class) {
// 使用UIAlertController...
} else {
// 使用旧的方案...
}
// Weakly Linked判断
if ([UIAlertController class]) {
// 使用UIAlertController...
} else {
// 使用旧的方案...
}
2. NS_CLASS_DEPRECATED_IOS
#define NS_CLASS_DEPRECATED_IOS(_iosIntro, _iosDep, ...) NS_CLASS_DEPRECATED(NA, NA, _iosIntro, _iosDep, __VA_ARGS__)
// 在某个版本开始引进一个方法,但是在某个版本之后废弃了
// NA表示从未支持过
// 第三个参数是编译警告的提示语
网友评论