iOS11.0 & iPhoneX适配在实践中的总结

iOS11.jpg

终于抽出时间整理下前段时间的适配工作
分两部分(iOS11 / iPhoneX)介绍一下个人在适配工作中遇到的实际的问题
共勉!

适配iOS11.0

首先看看跑在 iPhone8 模拟器上的效果

1.自定义导航栏上的控件不见了
屏幕快照 2017-11-06 上午10.21.35.png

原因
iOS11 的UINavigationBar有两个子视图,分别是UIBarBackground和UINavigaitonBarContentView,我们重点放在后者身上,因为BarButtonItem和TitleLabel都被添加到他上面。


屏幕快照 2017-11-06 上午9.55.54.png

解决方法
创建一个UINavigationBar的子类,重写layoutSubviews

/**
 为适配iOS11,解决导航栏上的控件向上飘了20pt的效果
 让创建的UINavigationBar继承自RootNavigationBar这个类
 */
-(void)layoutSubviews
{
    [super layoutSubviews];
    //#define NAVIGATION_HEADER_HEIGHT (iPhoneX ? 88.f : 64.f)
    self.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), NAVIGATION_HEADER_HEIGHT);
    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 = STATUSBAR_HEIGHT;
            frame.size.height = self.bounds.size.height - frame.origin.y;
            view.frame = frame;
        }
    }
}
2.tableView向下偏移了20pt
屏幕快照 2017-11-06 上午9.50.12.png

原因
iOS 11中Controller的automaticallyAdjustsScrollViewInsets属性被废弃了,所以当tableView超出安全区域时系统自动调整了SafeAreaInsets值,进而影响adjustedContentInset值,在iOS 11中决定tableView的内容与边缘距离的是adjustedContentInset属性,而不是contentInset。
解决方法
找到控制器的根类,或者相应的控制器的tableView中,添加如下代码

if (@available(iOS 11.0, *)) {
    _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}

完成1,2适配后的正常效果


屏幕快照 2017-11-06 上午10.46.15.png
3.搜索框UI异常,少了状态栏高度20pt
屏幕快照 2017-11-06 上午10.53.00.png

原因
搜索控制器的navigationBar未适配
解决方法
将搜索控制器中的navigationBar定义为方法1中创建的类

@property (nonatomic, strong) YWRootNavigationBar *navigationBar;
self.navigationBar = [[YWRootNavigationBar alloc] init];
屏幕快照 2017-11-06 上午11.18.34.png
4.没有navigationBar的控制器向下偏移了20pt
屏幕快照 2017-11-06 下午3.16.16.png

原因
本质就是tableView向下偏移了20pt
解决方法

if (@available(iOS 11.0, *)) {
    self.tableView1.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
屏幕快照 2017-11-06 下午3.17.11.png
5.搜索框的变化
屏幕快照 2017-11-15 下午4.53.58.png

原因
iOS11中,searchBar的高度由原来的44变为56
解决方法

_locationSearchController.searchBar.frame = CGRectMake(0, 0, _locationSearchController.searchBar.frame.size.width, SEARCHBAR_HEIGHT);
屏幕快照 2017-11-15 下午4.55.56.png

屏幕快照 2017-11-15 下午4.56.13.png
6.预估高度 estimatedXXHeight

iOS11 中的 estimatedXXHeight 由默认的 0 变成了现在的默认 .AutomaticDimension ,导致高度计算出错,最后导致的现象就是上拉加载更多的时候UI 错乱、tableView视图的高度异常等一系列问题。重新置 0 即可。

if (@available(iOS 11.0, *)) {
    _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    _tableView.estimatedRowHeight = 0;
    _tableView.estimatedSectionHeaderHeight = 0;
    _tableView.estimatedSectionFooterHeight = 0;
}
7.iOS11后将 searchController 赋值给了 NavigationItem,通过属性 hidesSearchBarWhenScrolling 可以控制搜索栏是否在滑动的时候进行隐藏和显示
// A view controller that will be shown inside of a navigation controller can assign a UISearchController to this property to display the search controller’s search bar in its containing navigation controller’s navigation bar.
@property (nonatomic, retain, nullable) UISearchController *searchController API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvOS);

// If this property is true (the default), the searchController’s search bar will hide as the user scrolls in the top view controller’s scroll view. If false, the search bar will remain visible and pinned underneath the navigation bar.
@property (nonatomic) BOOL hidesSearchBarWhenScrolling API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvOS);
屏幕快照 2017-11-15 下午6.18.25.png
8.UINavigationBar 新增属性 BOOL值 prefersLargeTitles 来实现下面的效果,并可以通过 largeTitleTextAttributes来设置大标题的文本样式。设置大标题之后,导航栏的高度就会由之前的64pt变成 96pt。
屏幕快照 2017-11-15 下午6.27.37.png

屏幕快照 2017-11-15 下午6.27.52.png
9.导航栏变成了半透明的

竟然看到了藏在后面的刷新视图


屏幕快照 2017-12-02 下午2.27.47.png

于是,借助Xcode View Hierarchy Debug工具,并且打印一下navigationBar的description,发现alpha莫名其妙的成了0.9


屏幕快照 2017-12-02 下午2.52.20.png
屏幕快照 2017-12-02 下午2.51.47.png

解决方法
在创建navigationBar的方法中添加代码,解决

self.navigationBar.alpha = 1;
屏幕快照 2017-12-02 下午2.32.44.png

如果你的工程中,大面积出现这样的问题,你可以参考如下方法,这篇文章写的还是很不错的
http://www.jianshu.com/p/6a5552ec5099

10.导航栏自定义titleView点击事件不响应

解决方法


屏幕快照 2017-12-12 下午6.22.04.png

UIView有个属性 intrinsicContentSize ,固有大小。意思就是说我知道自己的大小,如果你没有为我指定大小,我就按照这个大小来。 比如:在使用AutoLayout的时候,UILabel是不用指定尺寸大小的,只需指定位置即可,就是因为,只要确定了文字内容,字体等信息,它自己就能计算出大小来。
所以,重写UIView的 - (CGSize)intrinsicContentSize 方法。新建XXXTitleView继承自UIView,添加如下代码:

- (CGSize)intrinsicContentSize
{
    return CGSizeMake(SCREEN_WIDTH - 50 * SCREEN_WIDTH / 375 * 2, 44);
}

在创建的时候,直接使用自定义的titleView即可。

iPhoneX

终于可以在iPhoneX模拟器上过把瘾了
先甩一波适配需要的宏定义

//适配iPhoneX
#define iPhoneX (SCREEN_WIDTH == 375.f && SCREEN_HEIGHT == 812.f ? YES : NO)
#define SEARCHBAR_HEIGHT (IOS_VERSION >= 11.0 ? 56 : 44)
#define STATUSBAR_HEIGHT (iPhoneX ? 44.f : 20.f)
//单纯指导航条高度
#define NAVIGATIONBAR_HEIGHT 44.f
//导航条+状态栏 高度
#define NAVIGATION_HEADER_HEIGHT (iPhoneX ? 88.f : 64.f)
#define TABBAR_HEIGHT (iPhoneX ? (49.f+34.f) : 49.f)
#define TABBAR_SAFEBOTTOM_MARGIN (iPhoneX ? 34.f : 0.f)
#define SAFEAREA_INSETS(view) ({UIEdgeInsets insets; if(@available(iOS 11.0, *)) {insets = view.safeAreaInsets;} else {insets = UIEdgeInsetsZero;} insets;})
1.app界面上下各空出大概40pt的高度
屏幕快照 2017-11-15 下午5.21.36.png
2.pop操作,页面下沉
屏幕快照 2017-11-15 下午5.26.04.png

原因
UIScrollView 的 contentInsetAdjustmentBehavior 属性默认为 automatic
解决方法

if (@available(iOS 11.0, *)) {
    self._tableView1.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
3.push操作,navigationBar上移
屏幕快照 2017-11-15 下午5.27.30.png

原因
没有对navigationController进行适配
解决方法
找到自定义的navigationController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = YIWANG_BG_COLOR;
    //适配值
    self.statusBarHeight = STATUSBAR_HEIGHT;
    self.navigationBarHeight = NAVIGATIONBAR_HEIGHT;
}
4.push操作,tabBar上移

在UINavigationController的基类重写pushViewController代理方法,在push的时候修正tabBar的frame

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [self navBarAnimationWithStatus:self.navigationBarHidden];
    if (self.viewControllers.count > 0) {
        viewController.hidesBottomBarWhenPushed = YES;
    }
    [super pushViewController:viewController animated:animated];
    // 修改tabBar的frame
    CGRect frame = self.tabBarController.tabBar.frame;
    frame.origin.y = [UIScreen mainScreen].bounds.size.height - frame.size.height;
    self.tabBarController.tabBar.frame = frame;
}
5.info.plist 新添 Privacy - Photo Library Additions Usage Description 键,跟 Privacy - Photo Library Usage Description的不同之处在于,前者允许你只写入图库,不需要读取。这样使得隐私权限更加细化。

你可能感兴趣的:(iOS11.0 & iPhoneX适配在实践中的总结)