详解iOS11、iPhone X、Xcode9 适配指南

2020-01-21 01:06:14于丽

另外,UINavigationBar 新增属性 BOOL值 prefersLargeTitles 来实现下面的效果,并可以通过 largeTitleTextAttributes 来设置大标题的文本样式

iOS11适配,iPhone,X适配,Xcode9,适配

有个界面使用到了导航栏按钮相关的frame,也发生了UI错乱,查看UI层级关系后发现,iOS11以前是直接把按钮加到了UINavigationBar上面,而iOS11则是先将按钮加到了_UITAMICAdaptorView,再加到_UIButtonBarStackView、_UINavigationBarContentView,接着才是UINavigationBar。因此如果需要获取导航栏按钮 frame 或者 superView,这里需要专门做下适配

iOS11适配,iPhone,X适配,Xcode9,适配

iOS10及以下版本导航栏按钮层级关系图

iOS11适配,iPhone,X适配,Xcode9,适配

iOS11导航栏按钮层级关系图

三、iPhone X的适配

下载完Xcode9之后,第一件事自然是在 iPhone X(模拟器)上过把瘾,然后编译后就发现报错了

由于iPhone X的状态栏是和其他版本手机差异比较大的,因此api 变化也比较大

先后做了以下适配

适配点一:项目中使用状态栏中图标判断当前网络的具体状态

iOS11适配,iPhone,X适配,Xcode9,适配
出错代码

打印的 Log 报出以下错误: Trapped uncaught exception 'NSUnknownKeyException', reason: '[<UIStatusBar_Modern 0x7fcdb0805770> valueForUndefinedKey:]: this class is not key value coding-compliant for the key foregroundView.'

iOS11适配,iPhone,X适配,Xcode9,适配

iPhone X

iOS11适配,iPhone,X适配,Xcode9,适配

其他手机

使用 runtime 打印其所有属性,发现以下差异


// 测试代码
#import <objc/runtime.h>
NSMutableString *resultStr = [NSMutableString string];
//获取指定类的Ivar列表及Ivar个数
unsigned int count = 0;
Ivar *member = class_copyIvarList([[application valueForKeyPath:@"_statusBar"] class], &count);
  
for(int i = 0; i < count; i++){
  Ivar var = member[i];
  //获取Ivar的名称
  const char *memberAddress = ivar_getName(var);
  //获取Ivar的类型
  const char *memberType = ivar_getTypeEncoding(var);
  NSString *str = [NSString stringWithFormat:@"key = %s       type = %s n",memberAddress,memberType];
   [resultStr appendString:str];
}
NSLog(@"%@", resultStr);