前言
iOS 11beta版已經(jīng)來了,正式版我想應(yīng)該也快了,作為一個iOS開發(fā)者,這意味著馬上就要著手來適配iOS 11了。在開始之前,我想對于iOS 11中的新特性,還是很有必要先了解一下的。總不能每次都是坐等別人的適配手冊吧。
這里并沒有提到新增加的ARKit
、CoreML
,我想這些新框架目前我們應(yīng)該還接觸不到。至于Drag & Drop
,這個還是蠻有意思的,有時間的時候可以整理下。
UIViewController
-
topLayoutGuide
,bottomLayoutGuide
這2個屬性被標(biāo)記為過期了,但是在Storyboard里設(shè)置約束的時候,還是會出現(xiàn)這2個屬性 -
automaticallyAdjustsScrollViewInsets
這個屬性也被標(biāo)記過期了,可以使用UIScrollView
的contentInsetAdjustmentBehavior
替代
UIScrollView
- 新增contentInsetAdjustmentBehavior屬性
替代之前UIViewController
的automaticallyAdjustsScrollViewInsets
,作用類似,會根據(jù)某些情況自動調(diào)整scrollview
的contentInset
(實際改變的是adjustedContentInset
屬性,contentInset
屬性不會變)
有4個可選值:
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
屬性
只讀屬性,這個屬性會根據(jù)safeAreaInsets
的變化而變化 -
UIScrollViewDelegate
新增scrollViewDidChangeAdjustedContentInset
,當(dāng)adjustedContentInset
變化時會調(diào)用
UIScrollView
的這幾個Inset的改變需要引起注意,他改變了原來的contentInset的邏輯(比如現(xiàn)在contentInset
不會受UINavigationBar
的isTranslucent
影響了),可能會對現(xiàn)有的項目中的頁面展示有影響,在項目適配iOS11時需要留意下。
UINavigationBar
- 新增
prefersLargeTitles: Bool
屬性
大標(biāo)題,默認為false,當(dāng)設(shè)置為true時,navigation bar會顯示大標(biāo)題,向上滑動頁面,navigation bar 會變小直到顯示成跟之前一樣,同時title位置會發(fā)生變化
navigationController?.navigationBar.prefersLargeTitles = true
效果如下:
滾動的過程中,通過打印navigation bar 的frame發(fā)現(xiàn),navigation bar 的高度會跟著變化
如果navigation bar是透明的,scrollview的
safeAreaInsets
屬性也會跟著變化大概關(guān)系是:
safeAreaInsets.top = navigationBar.frame.height+statusBar.height
UINavigationItem
- 新增
largeTitleDisplayMode
屬性
這個屬性配合navigation bar的大標(biāo)題使用的。
當(dāng)navigation bar啟用prefersLargeTitles
后,這個屬性才會生效,可以控制某個單獨的ViewController
中的large title顯示模式,有三個可選值:
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
簡單來說:
-
automatic
:與上一個navigation item設(shè)置的largeTitleDisplayMode
相同 -
always
: 總是啟用大標(biāo)題。剛開始有個誤解,always并不是說當(dāng)scrollview滾動的時候,navigation bar一直是大標(biāo)題模式,而是指,不管上一個viewcontroller設(shè)置的是什么,這個viewcontroller都是啟用大標(biāo)題 -
never
:總是顯示小標(biāo)題模式,就是我們正常看到的導(dǎo)航欄標(biāo)題樣式
關(guān)于如何修改largetitle
的樣式,目前尚沒找到正確的打開方式。以前通過navigationbar.titleTextAttributes
直接修改小標(biāo)題的樣式,對大標(biāo)題無效(至少目前看是無效的)。
- 新增
searchController
屬性
在navigation bar下面增加一個搜索框
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.backgroundColor = .white
navigationItem.searchController = searchController
效果如下:
- 新增
hidesSearchBarWhenScrolling:Bool
屬性
配合searchController
使用的,默認是true
。
這個屬性是控制searchController
默認是否顯示的。
通過上圖也可以看到,searchBar默認是隱藏的,當(dāng)下拉的時候才會顯示出來,再上拉又會隱藏。
當(dāng)設(shè)置為false時,searchBar會一直顯示,當(dāng)scrollview下拉時,searchBar會隨著scrollview往下走,上拉時,則固定在頂部不動。
如下圖:
有意思的是,當(dāng)
scrollview
下拉時,navigation bar
的高度是一直增大的(通過在scrollViewDidScroll
代理里打印navigation bar
的frame
就會發(fā)現(xiàn)),也就是系統(tǒng)實際上是通過增大navigation bar
的height
,來讓search bar
緊隨著scrollview
的content的。查看層級關(guān)系,會發(fā)現(xiàn),
searchBar
并不是navigation bar
的subview
。<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個可選值:
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
目前我測試的結(jié)果是,當(dāng)設(shè)置separatorInsetReference
為fromCellEdges
時,separator
的Inset就相當(dāng)于 cell.separatorInset
,當(dāng)設(shè)置為fromAutomaticInsets
時,tableView.separatorInset
和cell.separatorInset
都無效。(可能是我的打開方式不對?)
- 新增
performBatchUpdates
函數(shù),支持批量操作了
Swipe actions
主要是實現(xiàn)了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
的,并且細化了是左滑還是右滑,同時提供了很不錯的交互體驗。
下面代碼是實現(xiàn)了一個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])
}
先看效果:
下面看下里面涉及到的幾個類
- UIContextualAction
表示的是滑開后顯示的一個操作按鈕,它有下面幾個屬性:-
style
: 有2個可選值:.normal
和.destructive
,區(qū)別是背景色不同,.normal
是灰色,.destructive
是紅色。當(dāng)然如果手動設(shè)置了action.backgroundColor
,則以backgroundColor
為準(zhǔn)。
還有一個區(qū)別,下面會說。 -
title
: action顯示的文字,目前沒有發(fā)現(xiàn)api可以修改這個title的font和color -
image
: 設(shè)置action的圖片,設(shè)置了image就不會顯示文字了 -
handler
: 點擊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個參數(shù):
UIContextualAction
: 就是當(dāng)前所屬的action啦
UIView
: 可以理解成action所呈現(xiàn)出來的那個視圖。如果是action是文字的,view是一個叫做UIButtonLabel
的東東,如果是image的,view則是UIImageView
(Bool) -> Swift.Void
: 這個參數(shù)是一個閉包,他的作用是一個completionHandler
,在handler的定義上面,已經(jīng)給出了說明,意思是在handler里你應(yīng)該調(diào)用這個completionHandler
,以恢復(fù)到正常狀態(tài)(可以看上面那個效果圖,點擊action后,cell會恢復(fù)到未左滑的狀態(tài))如果不調(diào)用,點擊后就會是保持現(xiàn)有的左側(cè)滑開的狀態(tài)。
而且這個completionHandler
也需要一個Bool類型的參數(shù),傳true
和傳false
有什么區(qū)別呢?官方的說明是pass YES to the completionHandler if the action was actually performed
其實這個就是style
中的normal
和destructive
的另一個區(qū)別。
我們知道,destructive
的意思是危險操作,一般表示的是刪除。如果你調(diào)用completionHandler
傳的是true
,當(dāng)style=.destructive
時,系統(tǒng)會刪掉這個cell,沒錯,刪掉這個cell!按照官方的解釋可以理解成,destructive
就是刪除,你傳了true
,說明action actually performed
,那系統(tǒng)就會刪掉這個cell.
對于style=.normal
的,我試了,傳true
和false
,沒區(qū)別。
- UISwipeActionsConfiguration
它只有兩個屬性,一個是actions
數(shù)組,表明你可以添加多個action操作;還有一個叫performsFirstActionWithFullSwipe
,默認是true
,意思是當(dāng)你full swipe
(完全滑動)的時候,系統(tǒng)會自動執(zhí)行第一個action的handler,這個在上面的效果圖上也能看到。
右滑跟左滑類似,就不再說了。
結(jié)束語
目前就整理了這么多,如果有描述錯誤的,還望不吝賜教。
希望大家都順利完成iOS11的適配工作!????