iOSiOS开发指南ios 开发问题

What's new in iOS 11 - 部分iOS

2017-06-22  本文已影响6522人  是的蛮大人

前言

iOS 11beta版已经来了,正式版我想应该也快了,作为一个iOS开发者,这意味着马上就要着手来适配iOS 11了。在开始之前,我想对于iOS 11中的新特性,还是很有必要先了解一下的。总不能每次都是坐等别人的适配手册吧。

这里并没有提到新增加的ARKitCoreML,我想这些新框架目前我们应该还接触不到。至于Drag & Drop,这个还是蛮有意思的,有时间的时候可以整理下。

UIViewController

UIScrollView

 public enum UIScrollViewContentInsetAdjustmentBehavior : Int {
    case automatic // Similar to .scrollableAxes, but will also adjust the top & bottom contentInset when the scroll view is owned by a view controller with automaticallyAdjustsScrollViewContentInset = YES inside a navigation controller, regardless of whether the scroll view is scrollable
    case scrollableAxes // Edges for scrollable axes are adjusted (i.e., contentSize.width/height > frame.size.width/height or alwaysBounceHorizontal/Vertical = YES)
    case never // contentInset is not adjusted
    case always // contentInset is always adjusted by the scroll view's safeAreaInsets
}

UINavigationBar

navigationController?.navigationBar.prefersLargeTitles = true

效果如下:

大标题
滚动的过程中,通过打印navigation bar 的frame发现,navigation bar 的高度会跟着变化
如果navigation bar是透明的,scrollview的safeAreaInsets属性也会跟着变化
大概关系是:
safeAreaInsets.top = navigationBar.frame.height+statusBar.height

UINavigationItem

public enum LargeTitleDisplayMode : Int {
        /// Automatically use the large out-of-line title based on the state of the previous item in the navigation bar. An item with largeTitleDisplayMode=Automatic will show or hide the large title based on the request of the previous navigation item. If the first item pushed is set to Automatic, then it will show the large title if the navigation bar has prefersLargeTitles=YES.
        case automatic
        /// Always use a larger title when this item is top most.
        case always
        /// Never use a larger title when this item is top most.
        case never
    }

使用方法:

navigationItem.largeTitleDisplayMode = .never

简单来说:

关于如何修改largetitle的样式,目前尚没找到正确的打开方式。以前通过navigationbar.titleTextAttributes直接修改小标题的样式,对大标题无效(至少目前看是无效的)。

 let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.backgroundColor = .white
navigationItem.searchController = searchController

效果如下:

searchcontroller.gif searchcontroller2.gif
有意思的是,当scrollview下拉时,navigation bar的高度是一直增大的(通过在scrollViewDidScroll代理里打印navigation barframe就会发现),也就是系统实际上是通过增大navigation barheight,来让search bar紧随着scrollview的content的。
查看层级关系,会发现,searchBar并不是navigation barsubview
<img src='http://upload-images.jianshu.io/upload_images/2412938-05ab84f30acc7fcb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240' width='200' />

UITableView

public enum UITableViewSeparatorInsetReference : Int {
    // The value set to the separatorInset property is interpreted as an offset from the edges of the cell.
    case fromCellEdges
    // The value set to the separatorInset property is interpreted as an offset from the automatic separator insets.
    case fromAutomaticInsets
}

举个例子,TableView的separator默认左边会留15,如果要去掉这个空隙,顶头显示
iOS 11之前的写法:

table.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
cell.layoutMargins = .zero

iOS 11之后的写法:

table.separatorInsetReference = .fromCellEdges //默认就是fromCellEdges,所以可以不写这行代码
cell.separatorInset = .zero

目前我测试的结果是,当设置separatorInsetReferencefromCellEdges时,separator的Inset就相当于 cell.separatorInset,当设置为fromAutomaticInsets时,tableView.separatorInsetcell.separatorInset都无效。(可能是我的打开方式不对?)

Swipe actions

主要是实现了TableViewCell的左划和右划手势功能
UITableViewDelegate中,新增了两个delegate,如下:

// These methods supersede -editActionsForRowAtIndexPath: if implemented
// return nil to get the default swipe actions
@available(iOS 11.0, *)
optional public func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?

@available(iOS 11.0, *)
optional public func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?

可以看到,这2个delegate是为了取代原有的editActionsForRowAtIndexPath的,并且细化了是左滑还是右滑,同时提供了很不错的交互体验。
下面代码是实现了一个Star功能的左滑手势

func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        
       let action = UIContextualAction(style: .normal, title: "Star") { (action, view, handler) in
            self.starAction(indexPath: indexPath)
            handler(true)
        }
        action.backgroundColor = .green
        if let stared = stars[indexPath], stared {
            action.title = "Unstar"
            action.backgroundColor = .red
        }
        
        return UISwipeActionsConfiguration(actions: [action])
    }

先看效果:

leadingswipe.gif

下面看下里面涉及到的几个类

// call the completionHandler to reset the context to its normal state (e.g. when swiping, resets to unswiped state)
// pass YES to the completionHandler if the action was actually performed, to show a visual indication of the successful completion
public typealias UIContextualActionHandler = (UIContextualAction, UIView, (Bool) -> Swift.Void) -> Swift.Void

可以看到有3个参数:
UIContextualAction: 就是当前所属的action啦
UIView: 可以理解成action所呈现出来的那个视图。如果是action是文字的,view是一个叫做UIButtonLabel的东东,如果是image的,view则是UIImageView
(Bool) -> Swift.Void: 这个参数是一个闭包,他的作用是一个completionHandler,在handler的定义上面,已经给出了说明,意思是在handler里你应该调用这个completionHandler,以恢复到正常状态(可以看上面那个效果图,点击action后,cell会恢复到未左滑的状态)如果不调用,点击后就会是保持现有的左侧滑开的状态。
而且这个completionHandler也需要一个Bool类型的参数,传true和传false有什么区别呢?官方的说明是pass YES to the completionHandler if the action was actually performed
其实这个就是style中的normaldestructive的另一个区别。
我们知道,destructive的意思是危险操作,一般表示的是删除。如果你调用completionHandler传的是true,当style=.destructive时,系统会删掉这个cell,没错,删掉这个cell!按照官方的解释可以理解成,destructive就是删除,你传了true,说明action actually performed,那系统就会删掉这个cell.
对于style=.normal的,我试了,传truefalse,没区别。

结束语

目前就整理了这么多,如果有描述错误的,还望不吝赐教。
希望大家都顺利完成iOS11的适配工作!😂😂

上一篇 下一篇

猜你喜欢

热点阅读