What's new in iOS 11 - 部分iOS11新特性整理

前言

iOS 11beta版已經(jīng)來(lái)了,正式版我想應(yīng)該也快了,作為一個(gè)iOS開發(fā)者,這意味著馬上就要著手來(lái)適配iOS 11了。在開始之前,我想對(duì)于iOS 11中的新特性,還是很有必要先了解一下的??偛荒苊看味际亲葎e人的適配手冊(cè)吧。

這里并沒有提到新增加的ARKit、CoreML,我想這些新框架目前我們應(yīng)該還接觸不到。至于Drag & Drop,這個(gè)還是蠻有意思的,有時(shí)間的時(shí)候可以整理下。

UIViewController

  • topLayoutGuide, bottomLayoutGuide
    這2個(gè)屬性被標(biāo)記為過(guò)期了,但是在Storyboard里設(shè)置約束的時(shí)候,還是會(huì)出現(xiàn)這2個(gè)屬性
  • automaticallyAdjustsScrollViewInsets
    這個(gè)屬性也被標(biāo)記過(guò)期了,可以使用UIScrollViewcontentInsetAdjustmentBehavior替代

UIScrollView

  • 新增contentInsetAdjustmentBehavior屬性
    替代之前UIViewControllerautomaticallyAdjustsScrollViewInsets,作用類似,會(huì)根據(jù)某些情況自動(dòng)調(diào)整scrollviewcontentInset(實(shí)際改變的是adjustedContentInset屬性,contentInset屬性不會(huì)變)
    有4個(gè)可選值:
 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
}
  • 新增safeAreaInsets: UIEdgeInsets屬性
    只讀屬性,為了配合contentInsetAdjustmentBehavior使用
  • 新增adjustedContentInset: UIEdgeInsets屬性
    只讀屬性,這個(gè)屬性會(huì)根據(jù)safeAreaInsets的變化而變化
  • UIScrollViewDelegate新增scrollViewDidChangeAdjustedContentInset,當(dāng)adjustedContentInset變化時(shí)會(huì)調(diào)用
    UIScrollView的這幾個(gè)Inset的改變需要引起注意,他改變了原來(lái)的contentInset的邏輯(比如現(xiàn)在contentInset不會(huì)受UINavigationBarisTranslucent影響了),可能會(huì)對(duì)現(xiàn)有的項(xiàng)目中的頁(yè)面展示有影響,在項(xiàng)目適配iOS11時(shí)需要留意下。

UINavigationBar

  • 新增prefersLargeTitles: Bool屬性
    大標(biāo)題,默認(rèn)為false,當(dāng)設(shè)置為true時(shí),navigation bar會(huì)顯示大標(biāo)題,向上滑動(dòng)頁(yè)面,navigation bar 會(huì)變小直到顯示成跟之前一樣,同時(shí)title位置會(huì)發(fā)生變化
navigationController?.navigationBar.prefersLargeTitles = true

效果如下:

大標(biāo)題

滾動(dòng)的過(guò)程中,通過(guò)打印navigation bar 的frame發(fā)現(xiàn),navigation bar 的高度會(huì)跟著變化
如果navigation bar是透明的,scrollview的safeAreaInsets屬性也會(huì)跟著變化
大概關(guān)系是:
safeAreaInsets.top = navigationBar.frame.height+statusBar.height

UINavigationItem

  • 新增largeTitleDisplayMode屬性
    這個(gè)屬性配合navigation bar的大標(biāo)題使用的。
    當(dāng)navigation bar啟用prefersLargeTitles后,這個(gè)屬性才會(huì)生效,可以控制某個(gè)單獨(dú)的ViewController中的large title顯示模式,有三個(gè)可選值:
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

簡(jiǎn)單來(lái)說(shuō):

  • automatic:與上一個(gè)navigation item設(shè)置的largeTitleDisplayMode相同
  • always: 總是啟用大標(biāo)題。剛開始有個(gè)誤解,always并不是說(shuō)當(dāng)scrollview滾動(dòng)的時(shí)候,navigation bar一直是大標(biāo)題模式,而是指,不管上一個(gè)viewcontroller設(shè)置的是什么,這個(gè)viewcontroller都是啟用大標(biāo)題
  • never:總是顯示小標(biāo)題模式,就是我們正常看到的導(dǎo)航欄標(biāo)題樣式

關(guān)于如何修改largetitle的樣式,目前尚沒找到正確的打開方式。以前通過(guò)navigationbar.titleTextAttributes直接修改小標(biāo)題的樣式,對(duì)大標(biāo)題無(wú)效(至少目前看是無(wú)效的)。

  • 新增searchController屬性
    在navigation bar下面增加一個(gè)搜索框
 let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.backgroundColor = .white
navigationItem.searchController = searchController

效果如下:

searchcontroller.gif
  • 新增hidesSearchBarWhenScrolling:Bool屬性
    配合searchController使用的,默認(rèn)是true
    這個(gè)屬性是控制searchController默認(rèn)是否顯示的。
    通過(guò)上圖也可以看到,searchBar默認(rèn)是隱藏的,當(dāng)下拉的時(shí)候才會(huì)顯示出來(lái),再上拉又會(huì)隱藏。
    當(dāng)設(shè)置為false時(shí),searchBar會(huì)一直顯示,當(dāng)scrollview下拉時(shí),searchBar會(huì)隨著scrollview往下走,上拉時(shí),則固定在頂部不動(dòng)。
    如下圖:

searchcontroller2.gif

有意思的是,當(dāng)scrollview下拉時(shí),navigation bar的高度是一直增大的(通過(guò)在scrollViewDidScroll代理里打印navigation barframe就會(huì)發(fā)現(xiàn)),也就是系統(tǒng)實(shí)際上是通過(guò)增大navigation barheight,來(lái)讓search bar緊隨著scrollview的content的。
查看層級(jí)關(guān)系,會(huì)發(fā)現(xiàn),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

  • 新增separatorInsetReference屬性
    分割線相關(guān)的,有2個(gè)可選值:
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
}

舉個(gè)例子,TableView的separator默認(rèn)左邊會(huì)留15,如果要去掉這個(gè)空隙,頂頭顯示
iOS 11之前的寫法:

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

iOS 11之后的寫法:

table.separatorInsetReference = .fromCellEdges //默認(rèn)就是fromCellEdges,所以可以不寫這行代碼
cell.separatorInset = .zero

目前我測(cè)試的結(jié)果是,當(dāng)設(shè)置separatorInsetReferencefromCellEdges時(shí),separator的Inset就相當(dāng)于 cell.separatorInset,當(dāng)設(shè)置為fromAutomaticInsets時(shí),tableView.separatorInsetcell.separatorInset都無(wú)效。(可能是我的打開方式不對(duì)?)

  • 新增performBatchUpdates函數(shù),支持批量操作了

Swipe actions

主要是實(shí)現(xiàn)了TableViewCell的左劃和右劃手勢(shì)功能
UITableViewDelegate中,新增了兩個(gè)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個(gè)delegate是為了取代原有的editActionsForRowAtIndexPath的,并且細(xì)化了是左滑還是右滑,同時(shí)提供了很不錯(cuò)的交互體驗(yàn)。
下面代碼是實(shí)現(xiàn)了一個(gè)Star功能的左滑手勢(shì)

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

下面看下里面涉及到的幾個(gè)類

  • UIContextualAction
    表示的是滑開后顯示的一個(gè)操作按鈕,它有下面幾個(gè)屬性:
    • style: 有2個(gè)可選值:.normal.destructive,區(qū)別是背景色不同,.normal是灰色,.destructive是紅色。當(dāng)然如果手動(dòng)設(shè)置了action.backgroundColor,則以backgroundColor為準(zhǔn)。
      還有一個(gè)區(qū)別,下面會(huì)說(shuō)。
    • title: action顯示的文字,目前沒有發(fā)現(xiàn)api可以修改這個(gè)title的font和color
    • image: 設(shè)置action的圖片,設(shè)置了image就不會(huì)顯示文字了
    • handler: 點(diǎn)擊action后的回調(diào),它的定義如下:
// 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個(gè)參數(shù):
UIContextualAction: 就是當(dāng)前所屬的action啦
UIView: 可以理解成action所呈現(xiàn)出來(lái)的那個(gè)視圖。如果是action是文字的,view是一個(gè)叫做UIButtonLabel的東東,如果是image的,view則是UIImageView
(Bool) -> Swift.Void: 這個(gè)參數(shù)是一個(gè)閉包,他的作用是一個(gè)completionHandler,在handler的定義上面,已經(jīng)給出了說(shuō)明,意思是在handler里你應(yīng)該調(diào)用這個(gè)completionHandler,以恢復(fù)到正常狀態(tài)(可以看上面那個(gè)效果圖,點(diǎn)擊action后,cell會(huì)恢復(fù)到未左滑的狀態(tài))如果不調(diào)用,點(diǎn)擊后就會(huì)是保持現(xiàn)有的左側(cè)滑開的狀態(tài)。
而且這個(gè)completionHandler也需要一個(gè)Bool類型的參數(shù),傳true和傳false有什么區(qū)別呢?官方的說(shuō)明是pass YES to the completionHandler if the action was actually performed
其實(shí)這個(gè)就是style中的normaldestructive的另一個(gè)區(qū)別。
我們知道,destructive的意思是危險(xiǎn)操作,一般表示的是刪除。如果你調(diào)用completionHandler傳的是true,當(dāng)style=.destructive時(shí),系統(tǒng)會(huì)刪掉這個(gè)cell,沒錯(cuò),刪掉這個(gè)cell!按照官方的解釋可以理解成,destructive就是刪除,你傳了true,說(shuō)明action actually performed,那系統(tǒng)就會(huì)刪掉這個(gè)cell.
對(duì)于style=.normal的,我試了,傳truefalse,沒區(qū)別。

  • UISwipeActionsConfiguration
    它只有兩個(gè)屬性,一個(gè)是actions數(shù)組,表明你可以添加多個(gè)action操作;還有一個(gè)叫performsFirstActionWithFullSwipe,默認(rèn)是true,意思是當(dāng)你full swipe(完全滑動(dòng))的時(shí)候,系統(tǒng)會(huì)自動(dòng)執(zhí)行第一個(gè)action的handler,這個(gè)在上面的效果圖上也能看到。
    右滑跟左滑類似,就不再說(shuō)了。

結(jié)束語(yǔ)

目前就整理了這么多,如果有描述錯(cuò)誤的,還望不吝賜教。
希望大家都順利完成iOS11的適配工作!????

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • iOS 11 為整個(gè)生態(tài)系統(tǒng)的 UI 元素帶來(lái)了一種更加大膽、動(dòng)態(tài)的新風(fēng)格。 本文介紹iOS11中在UI方面做了哪...
    阿凡提說(shuō)AI閱讀 639評(píng)論 0 1
  • UIScrollView and UITableView的新特性 ScrollView 如果有一些文本位于UI滾動(dòng)...
    透支未來(lái)閱讀 653評(píng)論 0 0
  • 一、NavigationBar UIBarItem UIBarItem在iOS11在中新增landscapeIma...
    灰s閱讀 3,933評(píng)論 5 11
  • 羨慕那些會(huì)畫畫的人 因?yàn)樗麄兡馨研那椴卦诋嬂?也羨慕那些會(huì)唱歌的人 因?yàn)樗麄兡馨炎约翰卦诟枥?而我 只能藏在夜里
    南嘉i閱讀 160評(píng)論 0 0
  • 你說(shuō),遇見我, 亂世突惹一身愁, 夜無(wú)點(diǎn)蠟, 日無(wú)酥油, 混得不如狗。 但你,可知否, 為苦苦尋你, 我一夜白頭,...
    倫小讓閱讀 639評(píng)論 9 3

友情鏈接更多精彩內(nèi)容