我的iOS11及iPhoneX适配(一)
我做的项目,在更新xcode到9.0,sdk版本是iOS11,如果不适配,暂时发现以下问题:
1.
2
3
以下是解决方案:
问题1:问题原因是iOS 11中Controller的automaticallyAdjustsScrollViewInsets属性被废弃了,所以当tableView超出安全区域时系统自动调整了SafeAreaInsets值,进而影响adjustedContentInset值,在iOS 11中决定tableView的内容与边缘距离的是adjustedContentInset属性,而不是contentInset。因为系统对adjustedContentInset值进行了调整,所以导致tableView的内容到边缘的距离发生了变化,导致tableView下移了20pt(statusbar高度)或64pt(navigationbar高度)。
因此,我们来看看adjustedContentInset的计算方式:
Default is UIScrollViewContentInsetAdjustmentAutomatic.
*/@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior
adjustContentInset表示contentView.frame.origin偏移了scrollview.frame.origin多少;是系统计算得来的,计算方式由contentInsetAdjustmentBehavior决定。有以下几种计算方式:
1.UIScrollViewContentInsetAdjustmentAutomatic:如果scrollview在一个automaticallyAdjustsScrollViewContentInset = YES的controller上,并且这个Controller包含在一个navigation controller中,这种情况下会设置在top & bottom上 adjustedContentInset = safeAreaInset + contentInset不管是否滚动。其他情况下与UIScrollViewContentInsetAdjustmentScrollableAxes相同
2.UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滚动方向上adjustedContentInset = safeAreaInset + contentInset,在不可滚动方向上adjustedContentInset = contentInset;依赖于scrollEnabled和alwaysBounceHorizontal / vertical = YES,scrollEnabled默认为yes,所以大多数情况下,计算方式还是adjustedContentInset = safeAreaInset + contentInset
3.UIScrollViewContentInsetAdjustmentNever: adjustedContentInset = contentInset
4.UIScrollViewContentInsetAdjustmentAlways: adjustedContentInset = safeAreaInset + contentInset
当contentInsetAdjustmentBehavior设置为UIScrollViewContentInsetAdjustmentNever的时候,adjustContentInset值不受SafeAreaInset值的影响。
解决方法:网上的方法有好几种,我用的是以下方法:
设置tableView的contentInsetAdjustmentBehavior属性
如果不需要系统为你设置边缘距离,可以做以下设置:
//如果iOS的系统是11.0,会有这样一个宏定义“#define __IPHONE_11_0 110000”;如果系统版本低于11.0则没有这个宏定义#ifdef __IPHONE_11_0
if ([tableView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
#endif
contentInsetAdjustmentBehavior属性也是用来取代automaticallyAdjustsScrollViewInsets属性的,推荐使用这种方式。
另外,对于tableview的section之前的间隔问题,是由于在创建tableview的时候,设置了UITableView的style为UITableViewStyleGrouped,默认tableView开头和结尾是有间距的,不需要这个间距的话,可以通过实现heightForHeaderInSection方法(返回一个较小值:0.1)和viewForHeaderInSection(返回一个view)来去除头部的留白,底部同理。代码中只实现了heightForHeaderInSection方法,而没有实现viewForHeaderInSection方法。那样写是不规范的,只实现高度,而没有实现view,但代码这样写在iOS 11之前是没有问题的,iOS 11之后应该是由于开启了估算行高机制引起了bug。添加上viewForHeaderInSection方法后,问题就解决了。或者添加以下代码关闭估算行高,问题也得到解决。解决方法是:
_tableView.estimatedRowHeight = 0;
_tableView.estimatedSectionHeaderHeight = 0;
_tableView.estimatedSectionFooterHeight = 0;
对于问题2,也同样是这个问题。
问题3:对于这个问题,我也很奇怪,感觉这个跟升级了iOS11关系不大,但是看了代码,才知道问题
- (void)deleteBtnAction:(UIButton *)sender {
UITableViewCell *cell = (UITableViewCell *)[[sender superview] superview];
UITableView *tableView = (UITableView *)[[cell superview] superview];
NSIndexPath *path = [tableView indexPathForCell:cell];
[self.delegate clickDeleteBtnActionAssertModifyCell:path];
}
- (void)editBtnAction:(UIButton *)sender {
UITableViewCell *cell = (UITableViewCell *)[[sender superview] superview];
UITableView *tableView = (UITableView *)[[cell superview] superview];
NSIndexPath *path = [tableView indexPathForCell:cell];
[self.delegate clickEditBtnActionAssertModifyCell:path];
}
原来之前的代码是在button响应事件中取到NSIndexPath,在通过delegate回调,虽然这个逻辑不是很好,但是在之前的版本也没问题,但是在iOS11中,貌似页面的分层有变化,导致[[cell superview] superview]直接crash。
我给的解决办法是:
1、直接在cell新加block属性,在点击buttoon的时候,调用block,通过block中的NSIndexPath直接得到。
2、修改原代码delegate的参数,之间返回cell本身的self,在回调delegeate的tableview页面通过cell直接取到NSIndexPath,避免了现在的层层向上找superview的方法。
最终代码是:
- (void)deleteBtnAction:(UIButton *)sender {
if (self.delegate && [self.delegate respondsToSelector:@selector(clickDeleteBtnActionAssertModifyCell:)]) {
[self.delegate clickDeleteBtnActionAssertModifyCell:self];
}
}
- (void)editBtnAction:(UIButton *)sender {
if (self.delegate && [self.delegate respondsToSelector:@selector(clickEditBtnActionAssertModifyCell:)]) {
[self.delegate clickEditBtnActionAssertModifyCell:self];
}
}
在调用的地方,代码是:
// 删除
- (void)clickDeleteBtnActionAssertModifyCell:(TLQAssertModifyCell *)cell {
NSIndexPath *index = [identifyTableView indexPathForCell:cell];
// todo
}