您的位置:首页 > 移动开发 > IOS开发

iOS11 & iPhone X 适配指南

2017-09-20 09:37 701 查看
屏幕未充满?

相信一部分开发者已经在着手适配iPhone X 和iOS11 了,xcode9测试版运行自己的项目会发现项目没有充满屏幕,上下会有黑色区域的情况,大家别慌,这是没有设置对应的启动图,iPhone X对应像素 1125 * 2436

大家可以自己添加图片或者准备一张尺寸:1125 * 2436的启动图片, 移动到LaunchImage的Finder目录中, 并在LaunchImage中的Contents.json文件中增加 (注意Json格式):

{

    "extent" : "full-screen",

    "idiom" : "iphone",

    "subtype" : "2436h",

    "filename" : "图片名字.png",

    "minimum-system-version" : "11.0",

    "orientation" : "portrait",

    "scale" : "3x"

}

UITableview UICollectionView MJRefresh下拉刷新错乱

iOS11 UIScrollView and UITableView的新特性

如果有一些文本位于UI滚动视图的内部,并包含在导航控制器中,现在一般navigationContollers会传入一个contentInset给其最顶层的viewController的scrollView,在iOS11中进行了一个很大的改变,不再通过scrollView的contentInset属性了,而是新增了一个属性:adjustedContentInset,通过下面两种图的对比,能够表示adjustContentInset表示的区域:



contentInsetAdjustmentBehavior属性有以下几个枚举值

typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {  

    UIScrollViewContentInsetAdjustmentAutomatic, 

    UIScrollViewContentInsetAdjustmentScrollableAxes,

    UIScrollViewContentInsetAdjustmentNever,

    UIScrollViewContentInsetAdjustmentAlways,

}

@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior;

@property(nonatomic, readonly) UIEdgeInsets adjustedContentInset;

//adjustedContentInset值被改变的delegate

- (void)adjustedContentInsetDidChange; 

- (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView *)scrollView;

1 automatic 和scrollableAxes一样,scrollView会自动计算和适应顶部和底部的内边距并且在scrollView 不可滚动时,也会设置内边距.

2 scrollableAxes 自动计算内边距.

3 never不计算内边距

4 always 根据safeAreaInsets 计算内边距

在我们项目中写tableview的时候可以加下面的代码来解决此问题

if (@available(iOS 11.0, *)) {

    _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;

    _tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);//iPhoneX这里是88

    _tableView.scrollIndicatorInsets = _tableView.contentInset;

}

在我自己项目中,我发现如果用的系统的导航栏的话距离上部可为0反而加上会有问题,列表会下移你设置的数值

_tableView.contentInset = UIEdgeInsetsMake(0, 0, 49, 0);

  // 实际项目中这样也有出现列表的下面可能会被遮挡(针对部分项目,视情况而定) 针对我自己的项目我设置了向下导航栏的高度看似没有问题了

tableView cell高度问题和头视图尾视图会有很大间隙

这个应该是UITableView最大的改变。我们知道在iOS8引入Self-Sizing 之后,我们可以通过实现estimatedRowHeight相关的属性来展示动态的内容,实现了estimatedRowHeight属性后,得到的初始contenSize是个估算值,是通过estimatedRowHeight
x cell的个数得到的,并不是最终的contenSize,tableView不会一次性计算所有的cell的高度了,只会计算当前屏幕能够显示的cell个数再加上几个,滑动时,tableView不停地得到新的cell,更新自己的contenSize,在滑到最后的时候,会得到正确的contenSize。

Self-Sizing在iOS11下是默认开启的,Headers, footers, and cells都默认开启Self-Sizing,所有estimated 高度默认值从iOS11之前的 0 改变为UITableViewAutomaticDimension:

@property (nonatomic) CGFloat estimatedRowHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to
0 to disable

如果目前项目中没有使用estimateRowHeight属性,在iOS11的环境下就要注意了,因为开启Self-Sizing之后,tableView是使用estimateRowHeight属性的,这样就会造成contentSize和contentOffset值的变化,如果是有动画是观察这两个属性的变化进行的,就会造成动画的异常,因为在估算行高机制下,contentSize的值是一点点地变化更新的,所有cell显示完后才是最终的contentSize值。因为不会缓存正确的行高,tableView
reloadData的时候,会重新计算contentSize,就有可能会引起contentOffset的变化。iOS11下不想使用Self-Sizing的话,可以

通过以下方式关闭:

self.tableView.estimatedRowHeight = 0;

self.tableView.estimatedSectionHeaderHeight = 0;

self.tableView.estimatedSectionFooterHeight = 0;

安全区域(Safe Area)

从iOS 7以来,我们在整个操作系统中都有这些半透明的bars,苹果鼓励我们通过这些bars绘制内容,我们是通过viewController 的edgesForExtendedLayout属性来做这些的。

iOS 7 开始,在 UIViewController中引入的 topLayoutGuide 和 bottomLayoutGuide 在 iOS 11 中被废弃了!取而代之的就是safeArea的概念,safeArea是描述你的视图部分不被任何内容遮挡的方法。 它提供两种方式:safeAreaInsets或safeAreaLayoutGuide来提供给你safeArea的参照值,即
insets 或者 layout guide。 safeArea区域如图所示:



iOS11 为UIViewController和UIView增加了一个新的方法 - (void)viewSafeAreaInsetsDidChange;

这个方法如名字一样 在安全区域改变后会被调用, 我们可以在需要适配的UIViewController和UIView中重写这个方法, 并且在这个方法中来根据safeAreaInsets属性更新子视图控件的布局位置.

这里有一点要注意的是当UIViewController调用- (void)viewDidLoad时它的所有子视图的safeAreaInsets属性都等于UIEdgeInsetsZero, 也就是说在- (void)viewSafeAreaInsetsDidChange;方法调用前 是无法通过当前视图控制器的子视图获取到safeAreaInsets的,
不过获取当前window对象的safeAreaInsets属性用来计算也是可以的, 但是不建议这么做, 一个视图控制器的子视图的处理当然要以它所在的控制器为准.

(void)viewSafeAreaInsetsDidChange在UIViewController中第一次调用的时间是在- (void)viewWillAppear:(BOOL)animated调用之后, 在- (void)viewWillLayoutSubviews调用之前.

当然如果你要改变一个UIViewController的safeAreaInsets值, 可以通过设置addtionalSafeAreaInsets属性来实现, 例如你要自定义一些特殊的样式时.

如果你改变了一个UIViewController的safeAreaInsets属性值, - (void)viewSafeAreaInsetsDidChange也会被调用.

采用SB或者xib 布局 Autolayout 视图的 top 和 bottom 一般参照的是 Top Layout Guide 和 Bottom Layout Guide. 但是iOS11 废弃了改用安全区域(SafeArea)做参考来做适配









滑动删除会蹦?

在iOS8之后,苹果官方增加了UITableVIew的右滑操作接口,即新增了一个代理方法(tableView: editActionsForRowAtIndexPath:)和一个类(UITableViewRowAction),代理方法返回的是一个数组,我们可以在这个代理方法中定义所需要的操作按钮(删除、置顶等),这些按钮的类就是UITableViewRowAction。这个类只能定义按钮的显示文字、背景色、和按钮事件。并且返回数组的第一个元素在UITableViewCell的最右侧显示,最后一个元素在最左侧显示。从iOS
11开始有了一些改变,首先是可以给这些按钮添加图片了,然后是如果实现了以下两个iOS 11新增的代理方法,将会取代(tableView: editActionsForRowAtIndexPath:)代理方法:

// Swipe actions

// These methods supersede -editActionsForRowAtIndexPath: if implemented

- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath
*)indexPath

- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath
*)indexPath

这两个代理方法返回的是UISwipeActionsConfiguration类型的对象,创建该对象及赋值可看下面的代码片段:

- ( UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath
*)indexPath {

    //删除

    UIContextualAction *deleteRowAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive
title:@"delete" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {

        [self.titleArr removeObjectAtIndex:indexPath.row];

        completionHandler (YES);

    }];

    deleteRowAction.image = [UIImage imageNamed:@"icon_del"];

    deleteRowAction.backgroundColor = [UIColor blueColor];

    UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[deleteRowAction]];

    return config;

}

创建UIContextualAction对象时,UIContextualActionStyle有两种类型,如果是置顶、已读等按钮就使用UIContextualActionStyleNormal类型,delete操作按钮可使用UIContextualActionStyleDestructive类型,当使用该类型时,如果是右滑操作,一直向右滑动某个cell,会直接执行删除操作,不用再点击删除按钮,这也是一个好玩的更新。

滑动操作这里还有一个需要注意的是,当cell高度较小时,会只显示image,不显示title,当cell高度够大时,会同时显示image和title。我写demo测试的时候,因为每个cell的高度都较小,所以只显示image,然后我增加cell的高度后,就可以同时显示image和title了。见下图对比:



目前暂时遇到的问题解决,还是等20号正式版推出再做详细的适配和更改,毕竟测试版的问题和bug 还是很多的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: