更新iOS11后,发现有些地方需要做适配,整理后按照优先级分为以下三类:
- 单纯升级iOS11后造成的变化;
- Xcode9 打包后造成的变化;
- iPhoneX的适配
一、单纯升级iOS11后造成的变化
升级后,发现某个拥有tableView的界面错乱,组间距和contentInset错乱,因为iOS11中 UIViewController 的 automaticallyAdjustsScrollViewInsets 属性被废弃了,因此当tableView超出安全区域时,系统自动会调整SafeAreaInsets值,进而影响adjustedContentInset值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return
nil;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return
nil;
}
self.tableView.sectionHeaderHeight = 0;
self.tableView.sectionFooterHeight = 5;
[_optionTableView setContentInset:UIEdgeInsetsMake(-35, 0, 0, 0)];
self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
|
四、使用Xcode9 编译后发现的问题
1. 发现“fastSocket”第三方报错,具体原因是缺少C99的头文件,引入“#include <sys/time.h>”即可
2. 导航栏的新特性
原生的搜索栏样式发生改变
右边为iOS11样式,搜索区域高度变大,字体变大
查看 API 后发现,iOS11后将 searchController 赋值给了 NavigationItem,通过属性 hidesSearchBarWhenScrolling 可以控制搜索栏是否在滑动的时候进行隐藏和显示
1
2
3
4
|
@property (nonatomic, retain, nullable) UISearchController *searchController API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
|
另外,UINavigationBar 新增属性 BOOL值 prefersLargeTitles 来实现下面的效果,并可以通过 largeTitleTextAttributes 来设置大标题的文本样式
有个界面使用到了导航栏按钮相关的frame,也发生了UI错乱,查看UI层级关系后发现,iOS11以前是直接把按钮加到了UINavigationBar上面,而iOS11则是先将按钮加到了_UITAMICAdaptorView,再加到_UIButtonBarStackView、_UINavigationBarContentView,接着才是UINavigationBar。因此如果需要获取导航栏按钮 frame 或者 superView,这里需要专门做下适配
iOS10及以下版本导航栏按钮层级关系图
iOS11导航栏按钮层级关系图
三、iPhone X的适配
下载完Xcode9之后,第一件事自然是在 iPhone X(模拟器)上过把瘾,然后编译后就发现报错了
由于iPhone X的状态栏是和其他版本手机差异比较大的,因此api 变化也比较大
先后做了以下适配
适配点一:项目中使用状态栏中图标判断当前网络的具体状态
出错代码
打印的 Log 报出以下错误: Trapped uncaught exception 'NSUnknownKeyException', reason: '[<UIStatusBar_Modern 0x7fcdb0805770> valueForUndefinedKey:]: this class is not key value coding-compliant for the key foregroundView.'
iPhone X
其他手机
使用 runtime 打印其所有属性,发现以下差异
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#import <objc/runtime.h>
NSMutableString *resultStr = [NSMutableString string];
unsigned
int
count = 0;
Ivar *member = class_copyIvarList([[application valueForKeyPath:@
"_statusBar"
]
class
], &count);
for
(
int
i = 0; i < count; i++){
Ivar var = member[i];
const
char
*memberAddress = ivar_getName(var);
const
char
*memberType = ivar_getTypeEncoding(var);
NSString *str = [NSString stringWithFormat:@
"key = %s type = %s \n"
,memberAddress,memberType];
[resultStr appendString:str];
}
NSLog(@
"%@"
, resultStr);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
key = _inProcessProvider type = @
"<UIStatusBarStateProvider>"
key = _showsForeground type = B
key = _backgroundView type = @
"UIStatusBarBackgroundView"
key = _doubleHeightLabel type = @
"UILabel"
key = _doubleHeightLabelContainer type = @
"UIView"
key = _currentDoubleHeightText type = @
"NSString"
key = _currentRawData type = {超长。。}
key = _interruptedAnimationCompositeViews type = @
"NSMutableArray"
key = _newStyleBackgroundView type = @
"UIStatusBarBackgroundView"
key = _newStyleForegroundView type = @
"UIStatusBarForegroundView"
key = _slidingStatusBar type = @
"UIStatusBar"
key = _styleAttributes type = @
"UIStatusBarStyleAttributes"
key = _waitingOnCallbackAfterChangingStyleOverridesLocally type = B
key = _suppressGlow type = B
key = _translucentBackgroundAlpha type = d
key = _showOnlyCenterItems type = B
key = _foregroundViewShouldIgnoreStatusBarDataDuringAnimation type = B
key = _tintColor type = @
"UIColor"
key = _lastUsedBackgroundColor type = @
"UIColor"
key = _nextTintTransition type = @
"UIStatusBarStyleAnimationParameters"
key = _overrideHeight type = @
"NSNumber"
key = _disableRasterizationReasons type = @
"NSMutableSet"
key = _timeHidden type = B
key = _statusBarWindow type = @
"UIStatusBarWindow"
key = _statusBar ; type = @
"_UIStatusBar"
NSArray *children;
if
([[application valueForKeyPath:@
"_statusBar"
] isKindOfClass:NSClassFromString(@
"UIStatusBar_Modern"
)]) {
children = [[[[application valueForKeyPath:@
"_statusBar"
] valueForKeyPath:@
"_statusBar"
] valueForKeyPath:@
"foregroundView"
] subviews];
}
else
{
children = [[[application valueForKeyPath:@
"_statusBar"
] valueForKeyPath:@
"foregroundView"
] subviews];
}
|
适配点二:解决这个问题后项目跑起来发现,整个app界面上下各空出大概40pt的高度
经常从 Github 上下载项目把玩的老司机们都知道,有些老项目在模拟器上跑起来之后也会只有 iPhone 4(320*480)的布局空间,造成这个的原因是启动图使用 Launch Images Source 设置的时候没有勾选并设置对应的图片,解决方法如下
然而iPhone X更大的坑是屏幕的适配
首先看下屏幕尺寸
这张图反映出不少信息:
- iPhone X的宽度虽然和7是一样的,但是高度多出145pt
- 使用三倍图是重点,而且一般认为肉眼所能所能识别的最高的屏幕密度是300ppi,iPhone X已达到458ppi(查证发现三星galaxy系列的屏幕密度是522ppi)
在设计方面,苹果官方文档human-interface-guidelines有明确要求,下面结合图例进行说明:
展示出来的设计布局要求填满整个屏幕
填满的同时要注意控件不要被大圆角和传感器部分所遮挡
安全区域以外的部分不允许有任何与用户交互的控件
上面这张图内含信息略多
头部导航栏不予许进行用户交互的,意味着下面这两种情况 Apple 官方是不允许的
- 底部虚拟区是替代了传统home键,高度为34pt,通过上滑可呼起多任务管理,考虑到手势冲突,这部分也是不允许有任何可交互的控件
- 状态栏在非安全区域,文档中也提到,除非可以通过隐藏状态栏给用户带来额外的价值,否则最好把状态栏还给用户
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
原文链接:http://www.jianshu.com/p/f5ee206c7df0