我的iOS11及iPhoneX适配(一)

我做的项目,在更新xcode到9.0,sdk版本是iOS11,如果不适配,暂时发现以下问题:

1.








2

我的iOS11及iPhoneX适配(一)_第1张图片



3

我的iOS11及iPhoneX适配(一)_第2张图片





以下是解决方案:


问题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

}



你可能感兴趣的:(iOS)