终于抽出时间整理下前段时间的适配工作
分两部分(iOS11 / iPhoneX)介绍一下个人在适配工作中遇到的实际的问题
共勉!
适配iOS11.0
首先看看跑在 iPhone8 模拟器上的效果
1.自定义导航栏上的控件不见了
原因
iOS11 的UINavigationBar有两个子视图,分别是UIBarBackground和UINavigaitonBarContentView,我们重点放在后者身上,因为BarButtonItem和TitleLabel都被添加到他上面。
解决方法
创建一个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
原因
iOS 11中Controller的automaticallyAdjustsScrollViewInsets属性被废弃了,所以当tableView超出安全区域时系统自动调整了SafeAreaInsets值,进而影响adjustedContentInset值,在iOS 11中决定tableView的内容与边缘距离的是adjustedContentInset属性,而不是contentInset。
解决方法
找到控制器的根类,或者相应的控制器的tableView中,添加如下代码
if (@available(iOS 11.0, *)) {
_tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
完成1,2适配后的正常效果
3.搜索框UI异常,少了状态栏高度20pt
原因
搜索控制器的navigationBar未适配
解决方法
将搜索控制器中的navigationBar定义为方法1中创建的类
@property (nonatomic, strong) YWRootNavigationBar *navigationBar;
self.navigationBar = [[YWRootNavigationBar alloc] init];
4.没有navigationBar的控制器向下偏移了20pt
原因
本质就是tableView向下偏移了20pt
解决方法
if (@available(iOS 11.0, *)) {
self.tableView1.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
5.搜索框的变化
原因
iOS11中,searchBar的高度由原来的44变为56
解决方法
_locationSearchController.searchBar.frame = CGRectMake(0, 0, _locationSearchController.searchBar.frame.size.width, SEARCHBAR_HEIGHT);
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);
8.UINavigationBar 新增属性 BOOL值 prefersLargeTitles 来实现下面的效果,并可以通过 largeTitleTextAttributes来设置大标题的文本样式。设置大标题之后,导航栏的高度就会由之前的64pt变成 96pt。
9.导航栏变成了半透明的
竟然看到了藏在后面的刷新视图
于是,借助Xcode View Hierarchy Debug工具,并且打印一下navigationBar的description,发现alpha莫名其妙的成了0.9
解决方法
在创建navigationBar的方法中添加代码,解决
self.navigationBar.alpha = 1;
如果你的工程中,大面积出现这样的问题,你可以参考如下方法,这篇文章写的还是很不错的
http://www.jianshu.com/p/6a5552ec5099
10.导航栏自定义titleView点击事件不响应
解决方法
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的高度
2.pop操作,页面下沉
原因
UIScrollView 的 contentInsetAdjustmentBehavior 属性默认为 automatic
解决方法
if (@available(iOS 11.0, *)) {
self._tableView1.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
3.push操作,navigationBar上移
原因
没有对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;
}