美文网首页将来跳槽用iOS点点滴滴
适配iOS 11和iPhone X填过的坑

适配iOS 11和iPhone X填过的坑

作者: 劳模007_Mars | 来源:发表于2017-12-18 17:51 被阅读43次

    每年的WWDC大会都激动和紧张好一段时间。激动的是期待苹果的新产品带来的那些黑科技,尤其今年的iPhone10周年纪念款iPhone X。紧张的当然是iOS、Swift和Xcode的升级,又要加班了(ㄒoㄒ)。在这里跟大家分享一下适配iOS 11和iPhone X的过程中,遇到了一些坑。

    一、导航栏

    在解释导航栏变化之前先解释一个iOS 11的新特性:设置大标题,通过BOOL类型的prefersLargeTitles属性来设置。默认设置是不开启。

    //显示大标题“设置”
    
    self.navigationController.navigationBar.prefersLargeTitles = YES;
    
    self.navigationItem.title = @"设置";
    
    简书1.png

    其中LargeTitle还有三种样式可以选择:

    
    UINavigationItemLargeTitleDisplayModeNever//总是显示小标题
    
    UINavigationItemLargeTitleDisplayModeAlways//总是显示大标题
    
    UINavigationItemLargeTitleDisplayModeAutomatic//自动显示大标题或小标题。即初始时是大标题,滑动时大标题隐藏、显示小标题。
    

    通过navigationItem的largeTitleDisplayMode属性来设置:

    
    self.navigationItem.largeTitleDisplayMode =  UINavigationItemLargeTitleDisplayModeAutomatic;
    

    当然,只有当prefersLargeTitles为YES时largeTitleDisplayMode属性才生效,

    1、导航栏高度变化

    iOS 11之前导航栏默认高度为64pt(statusBar + NavigationBar),iOS11之后如果设置了prefersLargeTitles = YES则为96pt,默认情况下还是64pt。由于iPhoneX上出现了“刘海”,statusBar由以前的20pt变成了44pt,所以iPhoneX上高度变为88pt。

    2、导航栏图层变化

    iOS 11之前导航栏的title是添加在UINavigationItemView上面的,而navigationBarButton则是直接条件在navigationBar上面。如果设置了titleView,那么titleView也是直接添加在navigationBar上面的。


    简书2.png

    iOS 11之后,视图层级发生了变化,增添了新的管理类。navigationBar会添加在_UIButtonBarStackView上面,而_UIButtonBarStackView则添加在_UINavigationBarContentView上面。如果没有给titleView赋值,那么titleView会直接添加在_UINavigationBarContentView上面;如果赋值了titlev,那么titleview会添加在_UITAMICAdaptorView上面,_UITAMICAdaptorView会添加在_UINavigationBarContentView上面。


    简书3.png
    简书4.png
    所以如果你的项目是自定义的navigationBar,那么在iOS11上运行就可能出现布局错乱的bug,解决办法是重写UINavigationBar的layoutSubviews方法,调整布局。
    - (void)layoutSubviews {
        [super layoutSubviews];
         
        //注意导航栏及状态栏高度适配
        self.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), naviBarHeight);
        for (UIView *view in self.subviews) {
            if([NSStringFromClass([view class]) containsString:@"Background"]) {
                view.frame = self.bounds;
            }
            else if ([NSStringFromClass([view class]) containsString:@"ContentView"]) {
                CGRect frame = view.frame;
                frame.origin.y = statusBarHeight;
                frame.size.height = self.bounds.size.height - frame.origin.y;
                view.frame = frame;
            }
        }
    }
    

    二、UIScrollView、UITableView、UICollectionView

    在iOS 11之前,如果想要scrollView不偏移64pt,则设置automaticallyAdjustsScrollViewInsets = NO,现在iOS 11设备上运行出现最多问题应该就是tableview莫名奇妙的偏移20pt或者64pt了。原因就是iOS 11弃用了automaticallyAdjustsScrollViewInsets属性,取而代之的是UIScrollView新增的contentInsetAdjustmentBehavior属性。最终还是因为iOS 11新添了safeArea。

    另外,tableView的sectionHeader、sectionFooter高度与设置不符的问题,因为在iOS 11中如果不实现

    -tableView: viewForHeaderInSection:
    -tableView: viewForFooterInSection:
    

    则不会被调用

    -tableView: heightForHeaderInSection:
    - tableView: heightForFooterInSection:
    

    导致sectionHeader、sectionFooter的高度都变成了默认高度。
    iOS 11之前,设置sectionHeader、sectionFooter高度为0时,需要设置height=0.1,才会起作用,如果直接设置为0,则会使用默认高度。在iOS 11中默认使用Self-Sizing,tableView的estimatedRowHeight、estimatedSectionHeaderHeight、 estimatedSectionFooterHeight三个高度估算属性由默认的0变成了UITableViewAutomaticDimension,解决办法简单粗暴,就是实现对应方法或把这三个属性设为0。

    如果你使用了Masonry,那么你需要适配safeArea

    if (@available(iOS 11.0, *)) {
        make.edges.equalTo()(self.view.safeAreaInsets)
    } else {
        make.edges.equalTo()(self.view)
    }
    

    今天暂且录入这几个问题,后续继续更新

    相关文章

      网友评论

        本文标题:适配iOS 11和iPhone X填过的坑

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