美文网首页ios
iOS版本判断

iOS版本判断

作者: 子瑜愚 | 来源:发表于2017-07-01 21:55 被阅读677次

    ♪ 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系统版本宏,NSFoudationCFCoreFoudation两个框架每个版本号也有对应的宏,这两个框架的版本号是随着iOS系统版本号更新的。
    • 可以通过NSFoundationVersionNumberkCFCoreFoundationVersionNumber这两个常量获取当前SDK下NSFoudationCFCoreFoudation的版本号,都是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表示从未支持过
    // 第三个参数是编译警告的提示语
    

    具体参考


    相关文章

      网友评论

        本文标题:iOS版本判断

        本文链接:https://www.haomeiwen.com/subject/skmpxxtx.html