iOS 多版本适配

Deployment Target VS Base SDK

在做向下兼容时,有两个术语不得不了解:Deployment Target和Base SDK。
Base SDK一般就是最新的iOS版本,可通过:Build Settings -> Architecture查看。
Deployment Target是App可支持的最旧的iOS版本。

不支持的Frameworks

连接Deployment Target不存在的framework会导至动态连接器崩溃你的App。所以把不受支持的framework设置为“Optional”, 也被称为软连接(weak linking):

optionalFramework.png

动态检查类是否可用 Unsupported classes

  1. weak linking
  if ([SomeNewVersionClass class] != nil) {
    // that framework is available
  } else {
    //Fail gracefully
  }

如果没有进行软连接此方法会导至崩溃

  1. querying the runtime
  if (NSClassFromString(@"SomeNewVersionClass") != nil) {
    //available
  } else {
    //Fail gracefully
  }

Unsupported methods

//instance method:
if ([instance respondsToSelector:@selector(someNewMethod)]) {
  // Safe to use.
} else {
  //Fail gracefully
}
//class method:
if ([someClass respondsToSelector:@selector(someNewClassMethod)]) {
  //safe to use
} else {
  //Fail gracefully
}

Unsupported constants/C functions

有时deployment target会缺失一些常量,比如:extern NSString *和C函数。此情况下,我们可用NULL判定它是否存在
举个例子:
C函数ABAddressBookCreateWithOptions(...)iOS6才引进的,在iOS5版本的App可以这么做:

if (ABAddressBookCreateWithOptions != NULL) {
  //Safe to use
} else {
  //Fail gracefully
}

The same approach applies to constants. For example, iOS 4.0 introduced multitasking support. If you wanted to check for the existence of UIApplicationWillEnterForegroundNotification, you would simply validate it as so:

if (&UIApplicationWillEnterForegroundNotification) {
    //Safe to assume multitasking support
}
else {
    //Fail gracefully
}

Unsupported enumeration values

Checking for the existence of enumeration or bit mask values — the kind that you would find inside an NS_ENUM or NS_OPTIONS declaration — is incredibly difficult to check at runtime. Why?
Under the hood, an enumeration is just a method of giving names to numeric constants. An enum is replaced with an int when compiled, which always exists!
If you’re faced with the situation of needing to see if a certain enumeration exists, all you can do is either explicitly check the OS version (which isn’t recommended) or alternatively check against another API element that was introduced at the same time as the new enumeration value.
Note: Whichever way you do this, be sure to add adequate comments to any such code and consider wrapping the code in a dedicated compatibility helper.

Explicit iOS version checking

  1. 方法一
/*
 *  System Versioning Preprocessor Macros
 */ 

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

/*
 *  Usage
 */ 

if (SYSTEM_VERSION_LESS_THAN(@"4.0")) {
}

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"3.1.1")) {
}

上述方法不推荐使用,请使用苹果官方推荐的方法。

  1. 苹果推荐方法
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1)
{
    // Load resources for iOS 6.1 or earlier
}
else
{
    // Load resources for iOS 7 or later
}

条件编译

当你使用了最新的iOS版本才引进的框架,但是你的同事可能使XCode版本过低无法识别这个新框架导至编译不通过。
而你又没办法要求所有同事都更新到最新的XCode,此时你可以用条件编译,使代版本的XCode也可以编译通过。

#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
#import <CallKit/CallKit.h>
#endif

//...
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
        if (NSClassFromString(@"CXCallObserver") != nil) {
            CXCallObserver *callObserver = [CXCallObserver new];
            [callObserver setDelegate:self queue:nil];
            self.callObserver = callObserver;
        }
#endif
// ...
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
- (void)callObserver:(CXCallObserver *)callObserver callChanged:(CXCall *)call {
    if (!call.hasConnected && !call.hasEnded && !call.isOnHold && !call.isOutgoing ) {
        // 监听电话打入事件
    }
}
#endif

https://www.raywenderlich.com/42591/supporting-multiple-ios-versions-and-devices
http://stackoverflow.com/questions/14002304/how-to-import-social-framework-only-for-ios-6
http://stackoverflow.com/questions/3339722/how-to-check-ios-version
http://tutuge.me/2015/07/25/compatibility-with-macro-category-and-runtime/
http://roadfiresoftware.com/2014/01/the-right-way-to-check-the-ios-version-in-an-app/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容