iOS 11 安全区域适配总结

作者: sonialiu | 来源:发表于2017-09-12 19:39 被阅读62396次

本文为作者原创,未经作者允许不得转载。该文同时发表在腾讯bugly公众号:http://mp.weixin.qq.com/s/W1_0VrchCO50owhJNmJnuQ 欢迎阅读

导语:本文主要是对iOS 11下APP中tableView内容下移20pt或下移64pt的问题适配的一个总结。内容包括五个部分:问题的原因分析、adjustContentInset属性的计算方式、什么情况下的tableView会发生内容下移、有哪些解决方法、解决这个问题时遇到的另外一个小问题。

一、iOS 11下APP中tableView内容下移20pt或下移64pt的原因分析

问题如下图所示:

问题.png

1. 原因分析

原因是iOS 11中Controller的automaticallyAdjustsScrollViewInsets属性被废弃了,所以当tableView超出安全区域时系统自动调整了SafeAreaInsets值,进而影响adjustedContentInset值,在iOS 11中决定tableView的内容与边缘距离的是adjustedContentInset属性,而不是contentInsetadjustedContentInset的计算方式见本文第二部分内容。因为系统对adjustedContentInset值进行了调整,所以导致tableView的内容到边缘的距离发生了变化,导致tableView下移了20pt(statusbar高度)或64pt(navigationbar高度)。

如果你的APP中使用的是自定义的navigationbar,隐藏掉系统的navigationbar,并且tableView的frame为(0,0,SCREEN_WIDTH, SCREEN_HEIGHT)开始,那么系统会自动调整SafeAreaInsets值为(20,0,0,0),如果使用了系统的navigationbar,那么SafeAreaInsets值为(64,0,0,0),如果也使用了系统的tabbar,那么SafeAreaInsets值为(64,0,49,0)。关于什么情况下会发生内容下移的问题,本文第三部分有介绍。

2. 安全区域的概念

系统自动调整tableView内容偏移量,是根据安全区域来调整的。安全区域是iOS 11新提出的,如下图所示:


SafeArea of an interface.png

安全区域帮助我们将view放置在整个屏幕的可视的部分。即使把navigationbar设置为透明的,系统也认为安全区域是从navigationbar的bottom开始的。
安全区域定义了view中可视区域的部分,保证不被系统的状态栏、或父视图提供的view如导航栏覆盖。可以使用additionalSafeAreaInsets去扩展安全区域去包括自定义的content在你的界面。每个view都可以改变安全区域嵌入的大小,Controller也可以。

safeAreaInsets属性反映了一个view距离该view的安全区域的边距。对于一个Controller的根视图而言,SafeAreaInsets值包括了被statusbar和其他可视的bars覆盖的区域和其他通过additionalSafeAreaInsets自定义的insets值。对于view层次中得其他view,SafeAreaInsets值反映了view被覆盖的部分。如果一个view全部在它父视图的安全区域内,则SafeAreaInsets值为(0,0,0,0)。

二、 adjustContentInset属性的计算方式

首先看scrollView在iOS11新增的两个属性:adjustContentInsetcontentInsetAdjustmentBehavior

/* Configure the behavior of adjustedContentInset.
Default is UIScrollViewContentInsetAdjustmentAutomatic.
*/
@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior

adjustContentInset表示contentView.frame.origin偏移了scrollview.frame.origin多少;是系统计算得来的,计算方式由contentInsetAdjustmentBehavior决定。有以下几种计算方式:

  1. UIScrollViewContentInsetAdjustmentAutomatic:如果scrollview在一个automaticallyAdjustsScrollViewInsets = 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会发生上述问题

如果设置了automaticallyAdjustsScrollViewInsets = YES,那么不会发生问题,一直都是由系统来调整内容的偏移量。

接下来排查下自己的项目中哪些页面会发生以上问题。

当tableView的frame超出安全区域范围时,系统会自动调整内容的位置,SafeAreaInsets值会不为0,于是影响tableView的adjustContentInset值,于是影响tableView的内容展示,导致tableView的content下移了SafeAreaInsets的距离。SafeAreaInsets值为0时,是正常的情况。

需要了解每个页面的结构,看tableView是否被系统的statusbar或navigationbar覆盖,如果被覆盖的话,则会发生下移。也可以通过tableview.safeAreaInsets的值来确认是因为安全区域的问题导致的内容下移。

如下代码片段,可以看出系统对tableView向下调整了20pt的距离,因为tableView超出了安全区域范围,被statusbar覆盖。

tableview.contentInset: {64, 0, 60, 0}
tableview.safeAreaInsets: {20, 0, 0, 0}
tableview.adjustedContentInset: {84, 0, 60, 0}

四、这个问题的解决方法有哪些?

1. 重新设置tableView的contentInset值,来抵消掉SafeAreaInset值,因为内容下移偏移量 = contentInset + SafeAreaInset;

如果之前自己设置了contentInset值为(64,0,0,0),现在系统又设置了SafeAreaInsets值为(64,0,0,0),那么tableView内容下移了64pt,这种情况下,可以设置contentInset值为(0,0,0,0),也就是遵从系统的设置了。

2. 设置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属性的,推荐使用这种方式。

3. 通过设置iOS 11新增的属性addtionalSafeAreaInset;

iOS 11之前,大家是通过将Controller的automaticallyAdjustsScrollViewInsets属性设置为NO,来禁止系统对tableView调整contentInsets的。如果还是想从Controller级别解决问题,那么可以通过设置Controller的additionalSafeAreaInsets属性,如果SafeAreaInset值为(20,0,0,0),那么设置additionalSafeAreaInsets属性值为(-20,0,0,0),则SafeAreaInsets不会对adjustedContentInset值产生影响,tableView内容不会显示异常。这里需要注意的是addtionalSafeAreaInset是Controller的属性,要知道SafeAreaInset的值是由哪个Controller引起的,可能是由自己的Controller调整的,可能是navigationController调整的。是由哪个Controller调整的,则设置哪个Controller的addtionalSafeAreaInset值来抵消掉SafeAreaInset值。

五、遇到的另外一个与安全区域无关的tableView内容下移的问题

我的作品页面的tableView下移了约40pt,这里是否跟安全区域有关呢?

查了下页面结构,tableView的父视图的frame在navigationbar的bottom之下,tableView在父视图的安全区域内,打印出来tableView的SafeAreaInset值也是(0,0,0,0);所以不是安全区域导致的内容下移。

经过查看代码,发现tableView的style:UITableViewStyleGrouped类型,默认tableView开头和结尾是有间距的,不需要这个间距的话,可以通过实现heightForHeaderInSection方法(返回一个较小值:0.1)和viewForHeaderInSection(返回一个view)来去除头部的留白,底部同理。

iOS 11上发生tableView顶部有留白,原因是代码中只实现了heightForHeaderInSection方法,而没有实现viewForHeaderInSection方法。那样写是不规范的,只实现高度,而没有实现view,但代码这样写在iOS 11之前是没有问题的,iOS 11之后应该是由于开启了估算行高机制引起了bug。添加上viewForHeaderInSection方法后,问题就解决了。或者添加以下代码关闭估算行高,问题也得到解决。

self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;

相关文章

网友评论

  • 1ed8a30901a5:很棒哦,写的很好,学习了
  • Liusr:如果设置了automaticallyAdjustsScrollViewInsets = YES,那么不会发生问题,一直都是由系统来调整内容的偏移量。

    这个 不是废弃了吗?还跟他有关系?
  • Dwyane_Coding:写得很好
  • 丶Destinyxl:请教一个问题 , tableView 有tableHeaderView、group形式,ios11 存在第一个section距离tableHeaderView有一个固定的间距存在
  • Ecolean:你好,我用的是collectionview 然后设置了collectionView.contentInset = UIEdgeInsetsMake(290, 0, 0, 0), 每次pop 到当前界面时,collectionview下降约44px,设置了UIScrollViewContentInsetAdjustmentNever之后,界面无法滑动
  • Beyond无状态:博主 我在navigation的titleview上加textField 真机上 push的时候textField上移 pop的时候下移 模拟器上没有问题 这是怎么回事
  • 丶丶夏天:safeAreaInsets属性反映了一个view距离该view的安全区域的边距. 这句话始终读不懂
    sonialiu:@丶丶夏天 哈哈哈,不懂的话,应该是一个view的安全区域 你不知道是哪一块吧?如果知道是一个view的边界,并且知道view的安全区域是哪块区域,那这句话应该是不难理解的,虽然有点绕口,但是表达是准确的
  • PGOne爱吃饺子:楼主 你好,我在导航视图里面添加了一个tableView,它的frame为self的frame,但是我打印的时候为什么 self.tableView.contentInset 的值为{0,0,0,0}呢,应该为{64,0,0,0},求助一下
  • Beyond无状态:- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    CGFloat sectionHeaderHeight = 10;
    if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
    scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
    } else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
    scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 50, 0);
    }

    }
    博主 我这段代码现在应该怎么改啊
  • 写代码的小农民:很多人不会用最新的xcode开发的,所以iOS 11新加的属性是不能用的,但是又要适配iPhone X怎么办?我是一堆if else适配安全区域外的一些东西 好在一直用Autolayout改起来比较容易
    直持小崔:感觉苹果自己在作死 搞的 什么玩意 ++
    sonialiu:@写代码的小农民 新加的属性能用啊
  • 世界的一缕曙光:好文,手动点赞。
  • 骑老虎喊救命:你好,我现在在iPhone X模拟器上适配出现如下问题:随便push到一个界面,tabBar正常消失,pop后正常出现,再随便present一个界面,tabBar正常消失,然后dismiss也正常,这个再去push一个界面,问题来了,tabBar消失的不正常......请大神试试这种情况,会不会有这个问题
  • 维维豆奶1991:如果你的APP中使用的是自定义的navigationbar,隐藏掉系统的navigationbar,并且tableView的frame为(0,0,SCREEN_WIDTH, SCREEN_HEIGHT)开始,那么系统会自动调整SafeAreaInsets值为(20,0,0,0)...请问SafeAreaInsets值为(20,0,0,0)对视图的布局有什么影响
    Phoenix_f82c:嗯 contentInset - 20就行了
    sonialiu:@维维豆奶1991 如果视图是tableView的话,会导致内容下移20,跟把contentInset设置为20 一个效果
  • 勤奋的张神:博主你好,我想请问下,为啥我的app打开之后就跟之前的iPhone一样的界面,上面和下面都有一块黑色的区域不能显示,就跟以前的iPhone一样的感觉,但是我是代码适配的,启动的时候是获取系统的宽高,即[UIScreen mainScreen].bounds,无法全屏显示啊
  • 小呵呵呵:看了两遍终于搞清楚了:smile: ,讲的真👍
  • LikeSomeBody:tableview.adjustedContentInset: {84, 0, 60, 0} 为啥我这报 只读属性
  • 布袋的世界:tableView.contentInsetAdjustmentBehavior,这句话一定得升级为 xcode 9 才有吗?

  • _码奴:为啥我这样写:[self setAdditionalSafeAreaInsets:UIEdgeInsetsMake(-40, -40, -40, -40)];和[self setAdditionalSafeAreaInsets:UIEdgeInsetsMake(0, 0, 0, 0)];写效果是相同的,安全区根本没变化,但是[self setAdditionalSafeAreaInsets:UIEdgeInsetsMake(40, 40, 40, 40)];这样写安全区就会变小
  • 小灰是蜗牛君:那么 安全区域 背景色 有特定要求吗?还是说不能为黑色?
  • LuffyYa:厉害,真细致!
  • 壹点微尘:楼主,我的项目里面,设置了
    if (@available(iOS 11.0, *)) {
    self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    } else {
    self.automaticallyAdjustsScrollViewInsets = NO;
    }
    和tableView的frame:_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, kNav_Height, KScreenWidth, kScreenHeight) style:UITableViewStyleGrouped];
    当我从这个界面push到下一个界面,再pop回来的时候,tableView上面会有一个导航条高度的白条,这是什么原因引起的呢?
  • 华楠:博主,不好意思问下,我的项目里自定义了导航栏,我在APPdelegate里设置了contentInsetAdjustmentBehavior为UIScrollViewContentInsetAdjustmentNever,然后我在其他界面都做了适配,但是在选择图片的时候,要跳转到UIImagePickerController里,界面整体上移了大约64个单位,我怎么修改都没用作用,请问博主有解决办法吗
    华楠:@sonialiu 感谢博主,我把APPdelegate里的那句代码删了,就可以了。
    onlyOneByOne:@sonialiu 我也测到了 置顶的哥们挖个大坑里把它放下面吧,花了一下午填坑
    sonialiu:亲测,是因为[UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;这句话导致的
  • 华楠:感谢楼主的分享
  • honey缘木鱼:写的不错,mark
  • 阿两sama:我想说一下,安全区域不是对tableview的,而是对于scrollView的都有这个问题
    sonialiu:安全区域是UIView的属性。首先看scrollView在iOS11新增的两个属性:adjustContentInset 和 contentInsetAdjustmentBehavior。文中说adjustContentInset属性是scrollView的,系统调整内容距离边缘的距离肯定是对scrollView而言的啊,文中只是拿tableView当例子来说的吧
  • 6b69124ff056:你的分享解决了我很多时间 🙏
  • 小小球员:感谢分享,总结得很细致!想补充一点:关于 adjustContentInset 的计算方式,当UIScrollViewContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAutomatic 且 automaticallyAdjustsScrollViewInsets = YES 时,只有 scrollView 是控制器 view 的第一个子 view 或者 scrollView 是控制器的 view 时, adjustedContentInset = safeAreaInset + contentInset 才成立不管是否滚动,后续添加的scrollView的adjustedContentInset 计算方式与UIScrollViewContentInsetAdjustmentScrollableAxes相同。
    这点其实与iOS10当中设置 automaticallyAdjustsScrollViewInsets = YES 改变 scrollView.contentInset 生效条件是相同的:只有scrollView是控制器 view 的第一个子 view 或者 scrollView 是控制器的 view 时, scrollView.contentInset 才会被改变。
  • b2c7a522e27e:首先感谢博主把原理讲得非常清晰,受教了!!!
    从cocoaChina论坛里找到了终极解决方案:

    //解决iOS11,仅实现heightForHeaderInSection,没有实现viewForHeaderInSection方法时,section间距大的问题
    [UITableView appearance].estimatedRowHeight = 0;
    [UITableView appearance].estimatedSectionHeaderHeight = 0;
    [UITableView appearance].estimatedSectionFooterHeight = 0;

    //iOS11 解决SafeArea的问题,同时能解决pop时上级页面scrollView抖动的问题
    if (@available(iOS 11, *)) {
    [UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; //iOS11 解决SafeArea的问题,同时能解决pop时上级页面scrollView抖动的问题
    }

    请把我顶上去,让更多人收益,谢谢!
    b2c7a522e27e:@我本善良 调用一次就可以了,写到哪里都可以。你没有位置写就写到Appdelegate里面吧
    我本善良:感谢分享,上面的代码是需要在项目哪个地方去调用?:smile:
    3937b6c7719a:不用一个一个加了,save my ass:)
  • heller灬:我用的系统的导航栏,我设置了导航栏透明,tableview的frame设置为:
    CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame];
    CGRect rectNav = self.navigationController.navigationBar.frame;
    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.centerX.equalTo(self.view);
    make.top.equalTo(self.view).with.offset(-rectStatus.size.height-rectNav.size.height);
    make.left.equalTo(self.view).with.offset(0);
    make.right.equalTo(self.view).with.offset(0);
    make.bottom.equalTo(self.view).with.offset(0);
    }];
    我发现我的tableview向下偏移了20pt;
    1、首先我打印了:tableview.contentInset
    tableview.safeAreaInsets
    tableview.adjustedContentInset
    都是0。
    2.我的tableview是UITableViewStyleGrouped的,我已经实现了viewForHeaderInSection,heightForHeaderInSection,viewForFooterInSection,heightForFooterInSection这些方法;
    我按照的你的两种方法都处理了,还是一样呢?怎么找原因啊
    heller灬:解决了:
    if (@available(iOS 11, *))
    {
    UIView*searchbg=[[UIView alloc]init];
    searchbg.backgroundColor=[UIColor clearColor];
    [searchbg.heightAnchor constraintEqualToConstant: 44].active = YES;
    [searchbg.widthAnchor constraintEqualToConstant:Screen_Width-70].active=YES;
    self.navigationItem.titleView=searchbg;
    [searchbg addSubview:self.searchbar];
    [self.searchbar mas_makeConstraints:^(MASConstraintMaker *make) {
    make.centerX.equalTo(searchbg);
    make.top.equalTo(searchbg).with.offset(7.0);
    make.left.equalTo(searchbg).with.offset(0);
    make.right.equalTo(searchbg).with.offset(0);
    make.bottom.equalTo(searchbg).with.offset(-7.0);
    }];
    }
    else
    {
    self.navigationItem.titleView=self.searchbar;
    }
    heller灬:折腾半天终于找到问题了,是因为设置了:
    self.searchbar = [[UISearchBar alloc] init];
    self.navigationItem.titleView=self.searchbar;
    出现的问题,只要注释掉就没问题了。。。

    问题又来了。。怎么修改titleview上面的SearcheView?
    heller灬:@heller灬 我发现Xcode8.3编译的运行在iOS11真机上就没问题、Xcode9编译的运行在iOS11真机上就有问题、而且我还发现:因为我在navigation.titleView上设置了seachview,同一个代码两种编译运行在同一个系统为iOS11的设备上呈现的UI都不一样、这是什么原因啊
  • 风雨落山岚://如果iOS的系统是11.0,会有这样一个宏定义“#define __IPHONE_11_0 110000”;如果系统版本低于11.0则没有这个宏定义
    #ifdef __IPHONE_11_0
    if ([tableView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
    tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }
    #endif
    这句话放在哪呢
  • 帅帅滴小胖次:你好,我是继承UITableViewController的页面,我还添加了下拉刷新,用了系统的导航条和tabbarcontroller。因为11.0MJ下拉刷新出问题了,我加这个判断才能解决:
    if (@available(iOS 11.0, *)) {
    self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    self.tableView.contentInset = UIEdgeInsetsMake(VIEW_5_8_INCH ? 88 : 64, 0, VIEW_5_8_INCH ? 83 : 49, 0);
    self.tableView.scrollIndicatorInsets = self.tableView.contentInset;
    }
    楼主,这个top和bottom还要判断是不是iPhone X,请问还要其它好的解决方案吗?
  • lltree:楼主,我看了这个半天了,通过代码没有实现被往下偏移20pt,醉啊
    你好牛:@lltree 我也遇到了 设置了没用
    为什么
    sonialiu:@lltree tableView的内容被下移20pt。你写tableView的frame从(0,0)开始,就会出现的
  • Stone_熊小叔:https://mp.weixin.qq.com/s/W1_0VrchCO50owhJNmJnuQ是同一个人吗?大佬写的很👍
    sonialiu:是同一个人,文章开头有写
  • 心灵的远足:我使用系统NavigationBar,某些界面隐藏NavigationBar后,tableView高度从20开始了
    设置 tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever恢复正常了,但是跳转到下一个界面,下个界面导航栏出现时有些残影,动画非常不自然,请问有什么解决办法呢?
    心灵的远足:@404你懂得 不是一样,隐藏导航栏页面push到下个导航不隐藏导航的界面会出现动画残影的情况
    sonialiu:@心灵的远足 两个页面有没有设计到用searchbar当titleview的情况?我这边有人是用searchbar当titleview,页面切换时,动画不正常,不知道你的情况是不是这样的
  • brance:感谢作者,我在复制你的代码时xcode提示我变成了如下,应该不会有问题吧:#ifdef __IPHONE_11_0
    if ([_tableView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
    if (@available(iOS 11.0, *)) {
    _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }
    }
    #endif
    洁简:@404你懂得 原来如此
    brance:@404你懂得 好的,多谢大佬指点
    sonialiu:应该可以直接这样写:
    #ifdef __IPHONE_11_0
    if (@available(iOS 11.0, *)) {
    tv.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }
    #endif
    运行时系统的版本判断有很多种方法。你可以测下Xcode8下跑下代码,Xcode9下跑下iOS 11的设备,iOS 11之前的设备,都看下是否正常,正常的话就是没有问题的
  • 字母B一路向北:楼主感谢你的文章,但是我是自定义的导航栏(是重写了navigationBar)我发现高度貌似变成了44,您知道什么原因吗?急求!
    hext123:@字母B一路向北 我也是, 你解决了吗?
    字母B一路向北:@404你懂得 是我自定义的nav 高度变成了44.我明明定义的事64 的
    sonialiu:@字母B一路向北 没有清楚你描述的问题是什么?是内容下移了44吗?系统的nav是隐藏了吗?
  • Supersweet007:如何才能避免很多界面设置这些属性,如果不存在隐藏导航的VC的话,直接用系统给计算的就可以了,但是如果存在隐藏导航的界面,就会很多这样的麻烦计算,如何避免, 或者如何来构思更好一点
  • 独木舟的木:64pt = 20pt(statusbar高度)+ 44pt(navigationbar高度)
  • f7139db11dcd:对底部是否有影响, tabbar 是否从49 变成 88 ?这里需要对tabbar处理吗 ?请问如何处理 ?
  • f7139db11dcd:大神,请问一下,把全部tableview预高度三个属性设置为0,设置heightForHeaderInSection和viewForHeaderInSection 就可以了?
    第三大点即是最后一个句话提出,那么我如何判断SafeAreaInset 是 navigationController的属性还是controlller的属性?
  • 麦子_KB:深度好文,看来您这英文非常棒
  • Xavier_Lost:如果是底部有视图,在iphonex下用bottomLayoutGuide距离视图10个间距就不会遮挡,在iOS 11以下就不正常了....还有底部有个条是什么.....好恶心:sweat:
  • 长若执念:果然很细致,我看完,感觉懂了一些,写的很赞啊!
    sonialiu:@长若执念 哈哈,感谢认可
  • 1a5d82bd9ef9:总结的很及时也很细致,:+1:
    sonialiu:感谢认可
  • Tate_code:#ifdef __IPHONE_11_0 我发现这个宏在真机iOS10.3.3还是返回YES的,导致这个判断无效
    某非著名程序员:@sonialiu 咋判断,是不是iPhone X
    sonialiu:写#ifdef __IPHONE_11_0这个宏判断,是为了让代码在xcode8上也能运行
    sonialiu:你是不是理解错了,这个宏是在预编译阶段执行的,是看你的xcode版本的,你应该用的xcode9,所以这个宏是返回yes的,跑程序在iOS 10.3.3的真机上,就靠运行时的判断了:if ([tableView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]),iOS10上没有这个方法,因此设置Behavior的代码不执行。没有问题呀
  • 其实你懂De:zan赞
    sonialiu:@其实你懂De 谢
  • zhghzx张星:我都是使用的预估高度,但是在iOS 11上边高度都变成44了,怎么解决啊
    sonialiu:@zhghzx 我在demo上试了下,使用预估高度,设置好约束,然后cell高度正常,不会都变成44。所以 不知道你是遇到了什么问题
    zhghzx张星:@404你懂得 应该都设置好了啊,因为之前都没有问题的..预估高度不用计算实际高度呀
    sonialiu:@zhghzx 是不是约束没设置好? 即使使用预估高度,也是要计算好实际高度的吧,你看看计算实际高度的代码有没有问题
  • 2a6f767eace1:我没明白这句话:对于一个Controller的根视图而言,SafeAreaInsets值包括了被statusbar和其他可视的bars覆盖的区域和其他通过additionalSafeAreaInsets自定义的insets值。
    系统认为安全区域是从navigationbar的bottom开始的吗?怎么又包含各种bar覆盖的区域了。。。。
    sonialiu:@柴羊羊 你打印一下contentInset的值呢?我这边是可以抵消的,看我的打印:View.safeAreaInsets: {0, 0, 0, 0}
    tableView.safeAreaInsets: {0, 0, 0, 0}
    tableView.contentInsets: {0, 0, 0, 0}
    self.navigationController.additionalSafeAreaInsets: {-20, 0, 0, 0}
    tableView.adjustedContentInset: {0, 0, 0, 0}
    我的例子是只使用了系统的statusbar,改成使用系统的navigationbar,也是一样可以抵消掉的
    柴羊羊:@sonialiu 系统也认为安全区域是从navigationbar的bottom开始的,所以设置additionalSafeAreaInsets.top为负数,并不能抵消SafeAreaInset.top带来的对视图的影响。bottom的负数是可以抵消tabbar的影响的。
    看代码打印:
    (lldb) po NSStringFromUIEdgeInsets(self.additionalSafeAreaInsets)
    {-64, 0, -49, 0}
    (lldb) po NSStringFromUIEdgeInsets(self.view.safeAreaInsets)
    {64, 0, 0, 0}
    (lldb) po NSStringFromUIEdgeInsets(_tv.adjustedContentInset)
    {64, 0, 0, 0}
    (lldb) po NSStringFromUIEdgeInsets(_tv.safeAreaInsets)
    {64, 0, 0, 0}
    可能理解的不准确,请指正。
    sonialiu:那句话中说的是SafeAreaInsets值,这个值是表示view到view的安全区域的距离,而不是表示安全区域。系统认为安全区域是从navigationbar的bottom开始的,是的。如果你理解了SafeAreaInsets的值,这句话的含义应该就理解了,哈哈,表达的是有些蹩脚
  • 洁简:tableview跳转的时候总有上滑的感觉 也是这个原因吗
    TommyYaphetS:@洁简 if (@available(iOS 11.0, *)) {
    [[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
    }
    我直接全部改掉了..
    洁简:@TommyYaphetS UIScrollViewContentInsetAdjustmentNever 就好了
    TommyYaphetS:我也遇到了这个情况, scrollview 跳转, pop回来的时候发生上滑跳动....
  • 炒鸡范:苹果净搞这些自以为的自动适应,结果大家最终都禁用了。
    炒鸡范:@404你懂得 对于开发者来说,这些乱七八糟的inset offset简直要烦死:joy:
    sonialiu:@炒鸡范 苹果想着多做事情,大家做app的时候简单些,对于小公司想快速做出app的是有好处的。也给其他用户带来局限性吧,应该有利有弊
  • 一飞冲天哈:你好,我的视图整体下移了64个点,在iphoneX 的模拟器上运行的,导航栏是自定义的,是什么原因?谢谢
    一飞冲天哈:@花了辞 对,启动图叫设计弄下,再放进去就可以了
    sonialiu:@花了辞 没有设置启动图片导致的吧
    romancemystery:你现在解决这个问题了吗?我也遇到了一样的
  • 玉思盈蝶:看了一遍觉得好复杂,居然没看懂:smile:
    sonialiu:@玉思盈蝶 应该是你没有遇到问题,如果遇到了同样的问题,看这篇文章会有感触
    玉思盈蝶:@404你懂得 可能我比较菜,...哈哈
    sonialiu:@玉思盈蝶 你看其他评论,他们都嫌文章太简单了:joy_cat:
  • 格蓝_:居然把这个玩意儿弄这么细致,哥们,你可以,大写的服
    想象纸中:看作者的文笔特点感觉不像是“哥们”。???
    格蓝_:@404你懂得 匠人精神
    sonialiu:@BDCA_战白 因为很多人问,所以干脆总结一下,发给大家看好了。不明白的会觉得很复杂,弄清楚之后觉得很简单了
  • selice:好总结,学习了。
    sonialiu:@selice :stuck_out_tongue_winking_eye:
  • KFC是做基的:赞
    a561547eee74: KFC是做开封菜的
    我只是个仙:KFC是做开封菜的
    sonialiu:@KFC是做基的 谢谢:smile:
  • 知傲:不错

本文标题:iOS 11 安全区域适配总结

本文链接:https://www.haomeiwen.com/subject/bowmkxtx.html