iOS版本兼容以及部分iOS 11适配

Tips Xcode 配置理解
1.Base SDK

这里写图片描述
指的是当前编译用的SDK版本。简单来说就是表示当前使用的Xcode所支持的最高的SDK的版本,比如现在是用iOS 11来编译程序,那么最高的SDK也就是11
2.Deployment Target
这里写图片描述
指的是编译出的程序将在哪个系统版本上运行,它控制着运行应用需要的最低操作系统版本。简单来说是当前的设置的Target所支持的最低的iOS的版本,比如现在设置的8.0,那么最低运行适配版本就是8.0,再低可能就炸了

版本兼容面对的问题
1.若你想要体验最新的iOS 11的功能,又要兼容iOS 8.0版本,Base SDK设置为最新的iOS 11(默认即可)。Deployment Target设置为iOS 8.0。当然,你用到的iOS 11 的API,要确保它们不会在iOS 8.0上不会crash。2.团队开发,如果你比较猎奇,你已经升级了最新的Xcode9,那么你就能编译最新的SDK,支持iOS 11,但是你的同事比较保守,没有升级,还是停留在Xcode 8,那么最高支持也就是iOS 10.3,当你提交了代码,如果不做好不同版本之间的条件编译,会导致用旧版本Xcode同事报错无法编译

解决思路一:静态检查编译SDK阶段

静态检查,即在编译时段就检查当前SDK编译与构建应用是否能使用某个API或已经不支持某个API

1.__IPHONE_OS_VERSION_MIN_REQUIRED**

值等于Deployment Target,检查支持的最小系统版本。

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000 
//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

2.__IPHONE_OS_VERSION_MAX_ALLOWED

值等于Base SDK,即用于检查SDK版本的

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0 
//you can use iOS 11 APIs here because the SDK supports them 
//but the code may still crash if run on an iOS 8 device 
可以使用最新的iOS 11的API,开始支持的新功能。但是仍然可能会在iOS 8的设备上crash。
#else
//this code can’t use iOS 10 APIs as the SDK version doesn’t support them 
不能使用iOS 11的API,只能使用iOS 11之前的。
#endif

通过系统预设的宏定义进行条件编译

  • 1.每次发布新版本SDK的时候,都会伴随新的API供大家使用,因此为了做兼容,低版本还是用低版本方法,而新版本可以用高版本API来进行兼容
  • 2.宏只在编译阶段生效,只是纯粹的文本替换,被宏包起来的代码,在编译阶段已经决定是否运行了,如果已经运行到系统上,那么宏就已经没什么卵用,已经在编译阶段判定好使用哪段代码了
  • 3.那么问题来了,不同版本的Xcode要进行宏定义的条件编译不同适配的代码,才能保证SDK的兼容问题
#ifndef __IPHONE_11_0
#define __IPHONE_11_0 110000
#endif
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0
#else
#endif

这样只是保证了不同SDK之间的兼容问题,保证编译的时候不存在问题,那么跑进系统之后如何保证高版本API在低系统运行时也能兼容,那么就需要运行时检查系统版本

解决思路二:运行时检查系统版本

这里从StackOverFlow上搜集了一些判断当前系统版本的几个方法

  • 1.Xcode 9新方法

if (@available(iOS 11, *)) {}
如果要看available语法的介绍可以自行百度,一大把## - -

  • 2.NSFoundationVersionNumber
    iphone版本感觉10之前都可以用,貌似10之后有点问题了,稍微知道下就好了,反正我不用

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) { // here you go with iOS 7}

  • 3.UIDevice

if ([[ [UIDevice currentDevice] systemVersion] floatValue] >= 11.0) {}

该方法对于整数,float计算出来就不会有问题,那么当如果你的系统是11.2.1和11.2.2这个时候就会出现精度问题,毕竟float存在的精度问题随时会出现,这种简单的判断适用于整数大版本,小版本就无法精确判断了

  • 4.NSOperatingSystemVersion
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion]; 
NSLog(@"major--->%ld,minjor--->%ld,patch--->%ld",version.majorVersion,version.minorVersion,version.patchVersion); 
NSOperatingSystemVersion v = (NSOperatingSystemVersion){9,0,0}; // 判断操作系统是否大于等于v版本 
BOOL isRight = [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:v]; 
if (isRight) { 
              NSLog(@"当前版本大于指定版本"); 
} else { 
              NSLog(@"当前版本小于指定版本"); 
}
// 2017-09-27 15:43:01.540690+0800 测试Icon[28898:915470] major--->11,minjor--->0,patch--->0
// 2017-09-27 15:43:01.540811+0800 测试Icon[28898:915470] 当前版本大于指定版本

这种方法是iOS 8之后才有的,目前为止的话可以用了,毕竟已经最低支持iOS 8了,不用担心7了

  • 5.字符串比较
/* * 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")) { ...}

我用的就是这种方式但是需要注意的是,如果你系统版本是11.0,你指定的版本是11.0.0,这种情况下,你要知道11.0.0是比11.0版本大的,也就是说你用

SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.0.0")
返回的是NO

针对上面的方法举个例子

#ifndef __IPHONE_8_0
#define __IPHONE_8_0 80000
#endif 
// 编译时判断:检查SDK版本 兼容Xcode版本
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0 
// 运行时判断:检查当前系统版本 
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) { 
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Warning" message:@"Compatibility" preferredStyle:UIAlertControllerStyleAlert]; 
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { NSLog(@"Cancel"); }]]; 
[self presentViewController:alertController animated:YES completion:nil]; } 
else { 
// 用旧的代替 
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Warning" message:@"Compatibility" delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil]; 
[alertView show];
 }
#else 
// ...#endif
}

针对上面提到的知识点总结,这里老外有一个简单的回答

这里写图片描述

总结来说:编译时检查SDK版本(兼容Xcode),运行时检查系统版本(兼容系统)

iOS 11适配

适配详情可以参考如下链接iOS 11适配详解

下面都是我个人的感觉和做法
iPhone X 变化最大的是头部 & 底部非iPhone X :
StatusBar 高20px,NavigationBar 高44px,底部TabBar高49pxiPhone X:
StatusBar 高44px,NavigationBar 高44px,底部TabBar高83p
来来来,一句话搞定适配,把下面的代码放着这个下面

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

#ifndef __IPHONE_11_0
#define __IPHONE_11_0 110000
#endif
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0
// if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.0")) { 
if (@available(iOS 11.0, *)) { 
UIScrollView.appearance.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; 
UITableView.appearance.estimatedRowHeight = 0; 
UITableView.appearance.estimatedSectionFooterHeight = 0; 
UITableView.appearance.estimatedSectionHeaderHeight = 0; 
} else { 
// Fallback on earlier versions 
}
// 
}
#endif

个人的一些知识点记录,如果对于上面提到的有任何问题,各位大神请留言指点,谢谢了~~~

原文链接:http://blog.csdn.net/deft_mkjing/article/details/78114229

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

推荐阅读更多精彩内容