前言
最近公司的很多流量产品需要适配iOS 11 和iPhone X,由于公司的iPhone X到的比较晚,拖了好久才对这些流量产品进行更新。
问题
- 首先一个很明显的适配问题,就是打开app的时候没有全屏,这时候要加入一张对应尺寸的启动图片就可以。
- 竖屏尺寸:1125px × 2436px(375pt × 812pt @3x)
- 横屏尺寸:2436px × 1125px(812pt × 375pt @3x)
- 跟启动屏有关的当然还有一个问题,那就是获取屏幕的大小:[[UIScreen mainScreen] bounds].size 加入上面的图片就可以了
导航栏
-
navigationItem.titleView
= 自定义view
, 这时候这个自定义的view
的大小就会出现问题,而且有点击时间也不会触发。首先,在自定义titleview
里重写intrinsicContentSize
属性,代码如下@property(nonatomic, assign) CGSize intrinsicContentSize;
然后在 self.navigationItem.titleView = _titleView; 之前加入下面的代码:
_titleView.intrinsicContentSize = CGSizeMake(200, 40);
自定义的view
还是要设置frame
,不然不是iOS11还是可能出问题。
- 导航栏高度的变化
iOS11之前导航栏默认高度为64pt(这里高度指statusBar + NavigationBar),iOS11之后如果设置了prefersLargeTitles = YES
则为96pt,默认情况下还是64pt,但在iPhoneX上由于刘海的出现statusBar由以前的20pt变成了44pt,所以iPhoneX上高度变为88pt,由于刘海多出了24pt的高度,如果项目里隐藏了导航栏加了自定义按钮之类的,这里需要注意适配一下。
在viewSafeAreaInsetsDidChange
方法里面打印NSLog(@"%@",NSStringFromUIEdgeInsets(self.view.safeAreaInsets))
;即可知道安全区域的边界
-
在iOS7之后,我们在设置
UINavigationItem
的leftBarButtonItem
,rightBarButtonItem
的时候都会造成位置的偏移,我们经常习惯使用下面这个方法来调整下间距+(UIBarButtonItem *)fixedSpaceWithWidth:(CGFloat)width {` UIBarButtonItem *fixedSpace = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; fixedSpace.width = width; return fixedSpace; }
但是在iOS11没有效果了,可以通过过改变按钮的 contentEdgeInsets
和imageEdgeInsets
的值成功改变了按钮的偏移问题,单独设置contentEdgeInsets
也可达到一定的效果
底部tarbar
- iPhone x:
Tabbar
从49pt变为83pt,如果是自己定义的tabbar
需要自己加上34的高度,否则会点不到对应tabbar
。如果是隐藏的tabbar
的话,比如底部放了一个banner
广告的话,这时候也需要调整对应的高度,在xcode中调整了下如果隐藏tabbar
,还要在底部放广告的话可以距离底部24pt,苹果tabbar
多加了34,比点击距离多加了10pt,应该是让用户体验更加的好点,不然24的话感觉快点到底部触摸栏的样子。
UITableView and UICollectionView
-
在iOS 11上运行tableView向下偏移64px或者20px,因为iOS 11废弃了
automaticallyAdjustsScrollViewInsets
,而是给UIScrollView增加了contentInsetAdjustmentBehavior
属性。避免这个坑的方法是要判断if (@available(iOS 11.0, *)) { _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; }else { self.automaticallyAdjustsScrollViewInsets = NO; }
-
IOS11以后,
Self-Sizing
默认开启,包括Headers
,footers
。如果项目中没使用estimatedRowHeight
属性,在IOS11下会有奇奇怪怪的现象,默认如果不去实现viewForHeaderInSection
就不会调用heightForHeaderInSection
,尾部试图一样,因为IOS11之前,estimatedRowHeight
默认为0,Self-Sizing
自动打开后,contentSize
和contentOffset
都可能发生改变。可以通过以下方式禁用:self.tableView.estimatedRowHeight = 0; self.tableView.estimatedSectionHeaderHeight = 0; self.tableView.estimatedSectionFooterHeight = 0;
-
列表/页面偏移,设置工程中的UITableView、UICollectionView、UIScrollView的
contentInsetAdjustmentBehavior
属性,如下:if (@available(iOS 11.0, *)){ _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; }
总的来说所有继承与Scrollview 及其子类都需要设置 contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever
,每个设置很麻烦,没关系。由于UIView及其子类都遵循UIAppearance
协议,我们可以进行全局配置:
// AppDelegate 进行全局设置
if (@available(iOS 11.0, *)){
[[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
}
-
当你在tableView 里面嵌套collectionView 的时候有可能出现一下错误:
Assertion failure in -[UICollectionViewData validateLayoutInRect:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3694.4.18/UICollectionViewData.m:435 2017-11-15 15:59:08.616969+0800 tbEmojiGuangchang[70423:3415148] invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution.
libc++abi.dylib: terminate_handler unexpectedly threw an exception
只要在刷新collectionView之前调用[collectionView.collectionViewLayout invalidateLayout]
就行。
-(NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
[collectionView.collectionViewLayout invalidateLayout];
return 1;
}
-
相册权限
iOS11之后:默认开启访问相册权限(读权限),无需用户授权,无需添加NSPhotoLibraryUsageDescription
,适配iOS11之前的还是需要加的。 添加图片到相册(写权限),需要用户授权,需要添加NSPhotoLibraryAddUsageDescription
,相册的权限状态有以下四种状态:PHAuthorizationStatusNotDetermined = 0, // User has not yet made a choice with regards to this application PHAuthorizationStatusRestricted, // This application is not authorized to access photo data. // The user cannot change this application’s status, possibly due to active restrictions // such as parental controls being in place. PHAuthorizationStatusDenied, // User has explicitly denied this application access to photos data. PHAuthorizationStatusAuthorized // User has authorized this application to access photos data.
iOS11之前如果还没请求访问相册权限的话状态是:PHAuthorizationStatusNotDetermined
,用户如果点击不允许访问相册的话状态是:PHAuthorizationStatusDenied
,但是在iOS11就很奇葩,还没请求访问相册权限和用户如果点击不允许访问相册的状态都是PHAuthorizationStatusNotDetermined
,导致不能判断是否是用户点击不允许的操作,也就没办法弹出那个引导用户去设置开启相册权限的窗口。我这边的做法是如果应用是有需要添加相片到相册的,要提前请求相册功能:
oc 代码:
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
}];
swift 代码:
if #available(iOS 11.0, *) {
let library: PHAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
if(library == PHAuthorizationStatus.notDetermined){
PHPhotoLibrary.requestAuthorization { (status) in
}
}
}
- 位置权限
在IOS11,原有的NSLocationAlwaysUsageDeion
被降级为NSLocationWhenInUseUsageDeion
。因此,在原来项目中使用requestAlwaysAuthorization
获取定位权限,而未在plist文件中配置NSLocationAlwaysAndWhenInUseUsageDeion
,系统框不会弹出。建议新旧key值都在plist里配置,反正我试下来是没有问题,唯一的区别是使用requestAlwaysAuthorization
获取权限 IOS11系统弹框会把几种权限级别全部列出,供用户选择,显然更人性化了。快去更新你的info.plist
<!-- 位置 -->
<key>NSLocationUsageDescription</key>
<string>获取地理位置,精准推送服务</string>
<!-- 在使用期间访问位置 -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>获取地理位置,精准推送服务</string>
<!-- 始终访问位置 -->
<key>NSLocationAlwaysUsageDescription</key>
<string>App需要您的同意,才能始终访问位置</string>
<!-- iOS 11访问位置 -->
<key>NSLocationAlwaysAndWhenInUseUsageDeion</key>
<string>App需要您的同意,才能始终访问位置</string>
-
使用第三方网络监测库报错
解决方式如下:替换成如下代码:
__Check_Compile_Time(sizeof(ICMPHeader) == 8);
__Check_Compile_Time(offsetof(ICMPHeader, type) == 0);
__Check_Compile_Time(offsetof(ICMPHeader, code) == 1);
__Check_Compile_Time(offsetof(ICMPHeader, checksum) == 2);
__Check_Compile_Time(offsetof(ICMPHeader, identifier) == 4);
__Check_Compile_Time(offsetof(ICMPHeader, sequenceNumber) == 6)
后续更新...
-
跳转appStore评论的链接更换了,很正常,因为iOS11之后appStore就大改版了,当然跳到里面的链接应该也是会有所变化的,之前iOS11的链接是这样的:
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=XXXXXXXX&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8"
iOS11之后需要改称以下这样,当然iOS11之前这个链接也是适用的:
itms-apps://itunes.apple.com/cn/app/idXXXXXX?mt=8&action=write-review
-
UIToolBar 的坑,当你使用view集成UIToolBar的时候,这个时候使用xcode9运行的时候会发现一个非常坑的问题,就是在view的最顶层会多出一层UIToolBarContenVIew出来,到时你的整个view没办法点击,建议不要用UIToolbar来继承。
总结
以上是我在适配我的一些产品的时候碰到的一些问题,当然还有一些其他很小的细节有问题,只需要稍微调整就行,在这里就不提了,苹果每次更新一个大版本的时候都会出现各种各样的问题,很多东西也变得越来越复杂,后面有在项目中碰到问题会在继续更新~