iOS11 & iPhone X 适配之路
适配iOS 11有几天了,这中间遇到无数种坑,由于我们项目支持iPad支持横竖屏,改起来简直想哭,好了废话不多说,总结下iOS 11&iPhone X的适配过程中遇到的问题。
iOS 11适配
UISearchController with Navigation
UISearchController在iOS 11中有较大的改动,如果你项目中有用到,在Xcode 8.3上打包在iOS 11上还是可以正常使用,如果你使用Xcode9....
横屏 竖屏这样玩意已经不能看了
下面回顾下iOS 11之前是怎么添加使用的
self.tableView.tableHeaderView = _searchController.searchBar;
iOS 11 UISearchController使用在navigationItem添加了两个属性
- navigationItem.searchController
- navigationItem.hidesSearchBarWhenScrolling 默认为YES
iOS 11的使用
if (@available(iOS 11.0, *)) {
self.navigationItem.searchController = _searchController;
} else {
self.tableView.tableHeaderView = _searchController.searchBar;
}
效果
navigationItem.searchController现在能也可以根据滑动来隐藏SearchBar了,但是我遇到的问题不仅仅是这样的,如果你使用UISearchController下一级的页面也使用且hidesSearchBarWhenScrolling为YES,那么在执行push的时候画面会这样....
注意push和pop过程中导航条下面会有一条留白
这个问题很尴尬,我到现在还没有解决
下拉刷新
很多人都遇到下拉刷新错位的问题,我们项目中也遇到了,直接不能用,很伤心,这是与iOS 11使用新的机制有关,automaticallyAdjustsScrollViewInsets在iOS 11中被被废弃,然后在scrollerView中添加contentInsetAdjustmentBehavior一个这样的属性,为什么这个会影响到下拉刷新这个控件呢,下面我来简单的说一下。
通常iOS 实现下拉刷新是通过KVO观察者模式,监听UIScrollerView的contentOffset属性,在该属性发生变化时,获取contentoffset的y值,比对初始contentoffset
详情看下面的代码,简单说明下拉刷新实现部分原理
/*
originalInset:,原始偏移值,如果设置automaticallyAdjustsScrollViewInsets .top 偏移为navgationbar.height + statusBar.height
contentOffset:scrollerView现在的偏移值
headerHeight :刷新头部View的高度
ps.
originalInset = scrollView.contentInset,可以这样获取,只获取一次
*/
CGPoint contentOffset = [[change valueForKey:NSKeyValueChangeNewKey] CGPointValue];
if (originalInset.top - contentOffset.y > headerHeight) {
//让tableView悬停,显示正在刷新View
UIEdgeInsets inset = _scrollView.contentInset;
insetTop.top = originalInset.top + headerHeight;
_scrollView.contentInset = inset;
}
通过上面所说的automaticallyAdjustsScrollViewInsets的设置会影响到计算,iOS 11中不在使用,iOS 11 中scrollView.contentInset(初始偏移量为0),但是他又引入了一个新的属性adjustedContentInset,所有我们项目中计算出错,下拉刷新无法,往上滑触发,并进行下移,所有我对代码进行了如下修改
cgfloat originalTop = originalInset.top;
if (iOS 11){
originalTop = self.adjustedContentInset.top;
}
if (originalTop - contentOffset.y > headerHeight) {
UIEdgeInsets inset = _scrollView.contentInset;
insetTop.top = originalInset.top + headerHeight;
_scrollView.contentInset = inset;
}
上面代码是我修改的思路,上拉刷新也是同样的道理
iPhone X适配
如果你的app不需要竖屏,那么恭喜你,减少了很多麻烦,如果需要横屏就要多费些时间了
Safe area
Safe areaiPhone X的适配主要是要把可以操作的控件放到安全区域内
获取 SafeArea
属性
- safeAreaInsets
改属性可以获取安全区域 UIEdgeInsets
切记:
UIViewController中,safeAreaInsets在viewDidLoad之后才有值,如果你在viewDidLoad 中要使用会发现没有值
可以通过系统方法监听SafeArea改变
SafeArea 改变方法
- viewSafeAreaInsetsDidChange
UIViewController中使用 - safeAreaInsetsDidChange
UIView中使用,在重新设置View的Frame或横竖屏变化会调用
UITableView适配
-
contentView
Cell和headerView上的控件一定要放到contentView上,不然就是下面的这种情况,contentView会根据safe area自适应
headerView - heightForHeaderInSection设置无效
已经设置过heightForHeaderInSection 但是显示仍是这样
图片.png解决方法:
设置viewForHeaderInSection
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
return nil;
}
未完,持续更新~
参考文章链接
Updating Your App for iOS 11
Designing for iPhone X
你可能需要为你的APP适配iOS11
刘海 |关于iPhone X 的适配