前言
關(guān)于 iOS 10 UICollectionView的新特性,主要還是體現(xiàn)在如下3個(gè)方面
順滑的滑動(dòng)體驗(yàn)
現(xiàn)在基本上人人都離不開(kāi)手機(jī),手機(jī)的app也每天都有人在用。一個(gè)app的好壞由它的用戶體驗(yàn)決定。在可以滑動(dòng)的視圖里面,必須要更加絲滑柔順才能獲得用戶的青睞。這些UICollectionView的新特性可以讓你們的app比原來(lái)更加順滑,而且這些特性只需要你加入少量的代碼即可達(dá)到目的。
針對(duì)self-sizing的改進(jìn)
self-sizing的API在iOS8的時(shí)候被引進(jìn),iOS10中加入更多特性使cell更加容易去適配。
Interactive reordering重排
這個(gè)功能在iOS9的時(shí)候介紹過(guò)了,蘋果在iOS 10的API里面大大增強(qiáng)了這一功能。
目錄
1.UICollectionViewCell順滑的滑動(dòng)體驗(yàn)
2.UICollectionViewCell的Pre-Fetching預(yù)加載
3.UITableViewCell的Pre-Fetching預(yù)加載
4.針對(duì)self-sizing的改進(jìn)
5.Interactive Reordering
6.UIRefreshControl
一. UICollectionViewCell順滑的滑動(dòng)體驗(yàn)
眾所周知,iOS設(shè)備已良好的用戶體驗(yàn)贏得了廣大的用戶群。iOS系統(tǒng)在用戶點(diǎn)擊屏幕會(huì)立即做出響應(yīng)。而且很大一部分的操作是來(lái)自于用戶的滑動(dòng)操作。所以滑動(dòng)的順滑是使用戶沉浸在app中享受的必要條件。接下來(lái)我們就談?wù)刬OS 10 中增加了那些新特性。
我們先來(lái)看一下之前 UICollectionView 的體驗(yàn),假設(shè)我們每個(gè)cell都是簡(jiǎn)單的藍(lán)色,實(shí)際開(kāi)發(fā)app中,cell會(huì)比這復(fù)雜很多。 我們先生成100個(gè)cell。當(dāng)用戶滑動(dòng)不是很快的時(shí)候,還感覺(jué)不出來(lái)卡頓,當(dāng)用戶大幅度滑動(dòng),整個(gè)UICollectionView的卡頓就很明顯了。如果整個(gè)cell的DataSource又是從網(wǎng)絡(luò)加載的,那就更加卡頓了。效果如下圖。
如果這種app上架,用戶使用過(guò)后,很可能就直接給1星評(píng)價(jià)了。但是為什么會(huì)造成這種問(wèn)題呢?我們來(lái)分析一下,我們模擬一下系統(tǒng)如何處理重用機(jī)制的,效果如下圖
在上圖中,我們可以看出,當(dāng)cell準(zhǔn)備加載進(jìn)屏幕的時(shí)候,整個(gè)cell都已經(jīng)加載完成,等待在屏幕外面了。而且更重要的是,在屏幕外面等待加載的cell是整整一行!這一行的cell都已經(jīng)加載完數(shù)據(jù)。這是UICollectionView在用戶大幅度滑動(dòng)時(shí)卡頓的根本原因。用專業(yè)的術(shù)語(yǔ)來(lái)說(shuō),掉幀。
接下來(lái)我們就來(lái)詳細(xì)的說(shuō)說(shuō)掉幀的問(wèn)題。
當(dāng)今的用戶是很挑剔的,用戶需要一個(gè)很順滑的體驗(yàn),只要有一點(diǎn)卡頓,很可能一言不合就卸載app了。要想用戶感覺(jué)不到卡頓,那么我們的app必須幀率達(dá)到60幀/秒。用數(shù)學(xué)換算一下就是每幀16毫秒就必須刷新一次。
我們用圖標(biāo)來(lái)分析一下掉幀的問(wèn)題。下面會(huì)出現(xiàn)2種不同的幀。
第一種情況,下圖是當(dāng)用戶輕微的上下小幅度滑動(dòng)。這個(gè)時(shí)候每個(gè)cell的加載壓力都不大,iOS針對(duì)這種情況,已經(jīng)做了很好的優(yōu)化了,所以用戶感覺(jué)不到任何卡頓。這種情況是不會(huì)掉幀,用戶也希望能使用如此順滑的app。
第二種情況,當(dāng)用戶大幅度滑動(dòng),每個(gè)cell加載的壓力很大,也許需要網(wǎng)絡(luò)請(qǐng)求,也許需要讀取數(shù)據(jù)庫(kù),而且每次都加載一行cell出來(lái),這樣每個(gè)cell的加載時(shí)間都增加了,加載一行的總時(shí)間也就大大增加了,如下圖所示。這樣,不僅僅當(dāng)前幀在加載cell,總的時(shí)間還會(huì)擠壓到下一幀的時(shí)間里面去。這種情況下,用戶就感覺(jué)到了卡頓了。
我們換種方式在說(shuō)明一下2種情況下掉幀的情況。我們用下圖的標(biāo)準(zhǔn)來(lái)衡量一下上面2種情況。下圖分為2部分,上面紅色的區(qū)域,就是表示掉幀的區(qū)域,因?yàn)楦哂?6ms。紅色和綠色區(qū)域的分界線就在16ms處。y軸我們表示的是CPU在主線程中花費(fèi)的時(shí)間。x軸表示的是在用戶滑動(dòng)中發(fā)生的刷新事件。
針對(duì)上述掉幀的情況,繪制出實(shí)驗(yàn)數(shù)據(jù),如下圖。值得我們關(guān)注的是,曲線是很曲折的,非常的不平滑。當(dāng)用戶大幅度滑動(dòng)的時(shí)候,峰值超過(guò)了16ms,當(dāng)用戶慢速滑動(dòng)的時(shí)候,幀率又能保持在比較順滑的區(qū)域。處于綠色區(qū)域內(nèi)的cell加載壓力都是很小的。這就是時(shí)而掉幀時(shí)而順滑的場(chǎng)景。這種場(chǎng)景下,用戶體驗(yàn)是很糟糕的。
那怎么解決這么問(wèn)題的呢?我們來(lái)看下圖:
上圖中的曲線我們看著就很平緩了,而且這種情況也不會(huì)出現(xiàn)掉幀的情況了,每個(gè)滑動(dòng)中的時(shí)間都能達(dá)到60幀了。這是怎樣做到的呢?因?yàn)榘衙總€(gè)cell的加載事件都平分了,每個(gè)cell不會(huì)再出現(xiàn)很忙和很閑的兩個(gè)極端。這樣我們就取消了之前的波峰和波谷。從而讓該曲線達(dá)到近乎水平的直線。
如何讓每個(gè)cell都分?jǐn)偧虞d任務(wù)的壓力?這就要談到新的cell的生命周期了。
先來(lái)看看老的 UICollectionViewCell的聲明周期。當(dāng)用戶滑動(dòng)屏幕,屏幕外有一個(gè)cell準(zhǔn)備加載顯示進(jìn)來(lái)。
這個(gè)時(shí)候我們把這個(gè)cell從reuse隊(duì)列里面拿出來(lái),然后調(diào)用prepareForReuse方法。這個(gè)方法就給了cell時(shí)間,用來(lái)重置cell,重置狀態(tài),刷新cell,加載新的數(shù)據(jù)。
再滑動(dòng),我們就會(huì)調(diào)用cellForItemAtIndexPath方法了。這個(gè)方法里面就是我們開(kāi)發(fā)者自定義的填充cell的方式了。這里會(huì)填充data model,然后賦值給cell,再把cell返回給iOS系統(tǒng)。
當(dāng)cell馬上要進(jìn)入屏幕的時(shí)候,就會(huì)調(diào)用willDisplayCell的方法。這個(gè)方法給了我們app最后一次機(jī)會(huì),為cell進(jìn)入屏幕做最后的準(zhǔn)備工作。執(zhí)行完willDisplayCell之后,cell就進(jìn)入屏幕了。
當(dāng)cell完全離開(kāi)屏幕之后,就會(huì)調(diào)用didEndDisplayingCell方法。以上就是在iOS10之前的整個(gè)UICollectionViewCell的生命周期。
接下來(lái)我們就來(lái)看看iOS 10的UICollectionViewCell生命周期是怎么樣的。
這里還是和iOS9一樣的,當(dāng)用戶滑動(dòng)UICollectionView的時(shí)候,需要一個(gè)cell,我們就從reuse隊(duì)列里面拿出一個(gè)cell,并調(diào)用prepareForReuse方法。注意調(diào)用這個(gè)方法的時(shí)間,當(dāng)cell還沒(méi)有進(jìn)入屏幕的時(shí)候,就已經(jīng)提前調(diào)用這個(gè)方法了。注意對(duì)比和iOS 9的區(qū)別,iOS 9 是在cell上邊緣馬上進(jìn)入屏幕的時(shí)候才調(diào)用方法,而這里,cell整個(gè)生命周期都被提前了,提前到cell還在設(shè)備外面的時(shí)候。
這里還是和之前一樣,在cellForItemAtIndexPath中創(chuàng)建cell,填充數(shù)據(jù),刷新?tīng)顟B(tài)等等操作。注意,這里生命周期也比iOS 9提前了。
用戶繼續(xù)滑動(dòng),這個(gè)時(shí)候就有不同了!
這個(gè)時(shí)候我們并不去調(diào)用willDisplayCell方法了!這里遵循的原則是,何時(shí)去顯示,何時(shí)再去調(diào)用willDisplayCell。
當(dāng)cell要馬上就需要顯示的時(shí)候,我們?cè)僬{(diào)用willDisplayCell方法。
當(dāng)整個(gè)cell要從UICollectionView的可見(jiàn)區(qū)域消失的時(shí)候,這個(gè)時(shí)候會(huì)調(diào)用didEndDisplayingCell方法。接下來(lái)發(fā)生的事情和iOS9一樣,cell會(huì)進(jìn)入重用隊(duì)列中。
如果用戶想要顯示某個(gè)cell,在iOS 9 當(dāng)中,cell只能從重用隊(duì)列里面取出,再次走一遍生命周期。并調(diào)用cellForItemAtIndexPath去創(chuàng)建或者生成一個(gè)cell。
在iOS 10 當(dāng)中,系統(tǒng)會(huì)把cell保持一段時(shí)間。在iOS中,如果用戶把cell滑出屏幕后,如果突然又想回來(lái),這個(gè)時(shí)候cell并不需要再走一段的生命周期了。只需要直接調(diào)用willDisplayCell就可以了。cell就又會(huì)重新出現(xiàn)在屏幕中。這就是iOS 10 的整個(gè)UICollectionView的生命周期。
上面說(shuō)的iOS 10里面的場(chǎng)景同樣適用于多列的情況。 這時(shí)我們每次只加載一個(gè)cell,而不是每次加載一行的cell。當(dāng)?shù)谝粋€(gè)cell準(zhǔn)備好之后再叫第二個(gè)cell準(zhǔn)備。當(dāng)2個(gè)cell都準(zhǔn)備好了之后,接著我們?cè)僬{(diào)用willDisplayCell給每個(gè)cell,發(fā)送完這個(gè)消息之后,cell就會(huì)出現(xiàn)在屏幕上了。
這雖然看起來(lái)是一個(gè)很小的改動(dòng),但是這小小的改動(dòng)就提升了很多的用戶體驗(yàn)!
讓我們來(lái)看看上述的改動(dòng)對(duì)滑動(dòng)的影響
滑動(dòng)比iOS 9流程很多,這里可以看到整個(gè)過(guò)程都很平緩,不卡頓。
還是和iOS 9一樣,我們來(lái)模擬一下系統(tǒng)是如何加載cell的情況。
我們可以很明顯的看到,iOS 系統(tǒng)是一個(gè)個(gè)的加載cell的,一個(gè)cell加載完之后再去加載下一個(gè)cell。這里和iOS 9 的有很大的不同,iOS 9是加載整整一行的cell。
這是因?yàn)槲覀冇昧诵碌?UICollectionViewCell的生命周期。整個(gè)app完全沒(méi)有加一行代碼。現(xiàn)在iOS 10是絲滑的滑動(dòng)體驗(yàn)實(shí)在是太棒了!!
二. UICollectionViewCell的Pre-Fetching預(yù)加載
當(dāng)我們編譯iOS 10的app的時(shí)候,這個(gè)Pre-Fetching默認(rèn)是enable的。當(dāng)然,如果有一些原因?qū)е履惚仨氂玫絠OS 10之前老的生命周期,你只需要給collectionView加入新的isPrefetchingEnabled屬性即可。如果你不想用到Pre-Fetching,那么把這個(gè)屬性變成false即可。
collectionView.isPrefetchingEnabled = false
為了最佳實(shí)踐一下這個(gè)新特性。我們先改變一下我們加載cell的方式。我們把很重的讀取數(shù)據(jù)的操作,所有內(nèi)容的創(chuàng)建都放到cellForItemAtIndexPath方法里面去完成。保證我們?cè)趙illDisplayCell 和 didEndDisplayCell這兩個(gè)方法里面基本不做其他事情。最后,需要注意的是cellForItemAtIndexPath生成的某些cell,可能永遠(yuǎn)都不會(huì)被展示在屏幕上,有這樣一種情況,當(dāng)cell將要展示在屏幕上的時(shí)候,用戶突然滑動(dòng)離開(kāi)了這個(gè)界面。
如果這個(gè)時(shí)候當(dāng)你用iOS 10編譯出你的app,那么非常順滑的用戶體驗(yàn)就會(huì)自動(dòng)的優(yōu)化出來(lái)。
UICollectionView的流暢的滑動(dòng)解決了,那么在UICollectionViewCell在加載的時(shí)候所花費(fèi)的時(shí)間,怎么解決呢??
UICollectionViewCell加載的時(shí)間取決于DataModel。DataModel很可能回去加載圖片,來(lái)自于網(wǎng)絡(luò)或者來(lái)自于本地的數(shù)據(jù)庫(kù)。這些操作大多數(shù)都是異步的操作。為了使data加載更快,iOS 10引入了新的API來(lái)解決這個(gè)問(wèn)題。
UICollectionView有2個(gè)“小伙伴”,那就是data source和delegate。在iOS 10中,將會(huì)迎來(lái)第3個(gè)“小伙伴”。這個(gè)“小伙伴”叫prefetchDataSource。
protocol UICollectionViewDataSourcePrefetching {
func collectionView(_ collectionView: UICollectionView,
prefetchItemsAt indexPaths: [NSIndexPath])
optional func collectionView(_ collectionView: UICollectionView,
cancelPrefetchingForItemsAt indexPaths: [NSIndexPath])
}
class UICollectionView : UIScrollView {
weak var prefetchDataSource: UICollectionViewDataSourcePrefetching?
var isPrefetchingEnabled: Bool
}
這個(gè)協(xié)議里面只有一個(gè)必須要實(shí)現(xiàn)的方法——ColletionView prefetchItemsAt indexPaths。這個(gè)方法會(huì)在prefetchDataSource里面被調(diào)用,用來(lái)給你異步的預(yù)加載數(shù)據(jù)的。indexPaths數(shù)組是有序的,就是接下來(lái)item接收數(shù)據(jù)的順序,讓我們model異步處理數(shù)據(jù)更加方便。
在這個(gè)協(xié)議里面還有第二個(gè)方法CollectionView cancelPrefetcingForItemsAt indexPaths,不過(guò)這個(gè)方法是optional的。我們可以利用這個(gè)方法來(lái)處理在滑動(dòng)中取消或者降低提前加載數(shù)據(jù)的優(yōu)先級(jí)。
值得說(shuō)明的是,新增加的這個(gè)“小伙伴”prefetchDataSource并不能代替原來(lái)的讀取數(shù)據(jù)的方法,這個(gè)預(yù)加載僅僅只是輔助加載數(shù)據(jù),并不能 刪除原來(lái)我們讀取數(shù)據(jù)的方法。
至此,我們來(lái)看看從文章開(kāi)始到現(xiàn)在,UICollectionView的性能提升了多少。我們還是用掉幀的方法來(lái)看看UICollectionView的性能。
上圖是iOS 9 UICollectionView的性能,很明顯的看見(jiàn),波峰波谷很明顯,并且還掉了8幀,有明顯的卡頓現(xiàn)象。
上圖是iOS 10 UICollectionView的性能,我們可以很明顯的看到,經(jīng)過(guò)iOS 10的優(yōu)化,整個(gè)曲線很明顯平緩了一些,沒(méi)有極端的波峰掉幀現(xiàn)象。但是依舊存在少量的波峰快到16ms分界線了。
上圖是iOS 10 + Pre-Fetching API 之后的性能,已經(jīng)優(yōu)化的效果很明顯了!整條曲線基本都水平了。近乎完美。但是還是能發(fā)現(xiàn)有個(gè)別波峰特別高。波峰特別高的地方就是那個(gè)cell加載壓力大,時(shí)間花的比較長(zhǎng)導(dǎo)致的。接下來(lái)我們繼續(xù)優(yōu)化!
先來(lái)總結(jié)一下使用Pre-Fetching API需要注意的地方。
在我們使用Pre-Fetching API的時(shí)候,我們一定要保證整個(gè)預(yù)加載的過(guò)程都放在后臺(tái)線程中進(jìn)行。合理使用GCD 和 NSOperationQueue處理好多線程。
請(qǐng)切記,Pre-Fetching API是一種自適應(yīng)的技術(shù)。何為自適應(yīng)技術(shù)呢?當(dāng)我們滑動(dòng)速度很慢的時(shí)候,在這種“安靜”的時(shí)期,Pre-Fetching API會(huì)默默的在后臺(tái)幫我們預(yù)加載數(shù)據(jù),但是一旦當(dāng)我們快速滑動(dòng),我們需要頻繁的刷新,我們不會(huì)去執(zhí)行Pre-Fetching API。
最后,用cancelPrefetchingAPI去迎合用戶的滑動(dòng)動(dòng)作的變換,比如說(shuō)用戶在快速滑動(dòng)突然發(fā)現(xiàn)了有趣的感興趣的事情,這個(gè)時(shí)候停下來(lái)滑動(dòng)了,甚至快速反向滑動(dòng)了,或者點(diǎn)擊了事件,進(jìn)去看詳情了,這些時(shí)刻我們都應(yīng)該開(kāi)啟cancelPrefetchingAPI。
綜上所述,Pre-Fetching API對(duì)于提高UICollectionView的性能提升是很有幫助的,而且并不需要加入太多的代碼。加入少量的代碼就可以獲得巨大的性能提升!
三. UITableViewCell的Pre-Fetching預(yù)加載
在iOS 10中,UITableViewCell也跟著UICollectionView一起得到了性能的提升,一樣擁有了Pre-Fetching API。
protocol UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [NSIndexPath])
optional func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths:
[NSIndexPath])
}
class UITableView : UIScrollView {
weak var prefetchDataSource: UITableViewDataSourcePrefetching?
}
這里和上面 UICollectionView一樣,會(huì)調(diào)用TableView prefetchRowsAt indexPaths方法。indexPaths還是一個(gè)有序數(shù)字,順序就是列表上可見(jiàn)的順序。第二個(gè)可選的API還是TableView cancelPrefetchingForRowsAt indexPaths,和之前提到的一樣,也是用來(lái)取消預(yù)加載的。性能的提升和UICollectionView一樣的,對(duì)UITableView的性能提升很大!
四. 針對(duì)self-sizing的改進(jìn)
self-sizing API 第一次被引入是在iOS 8,然而現(xiàn)在在iOS 10中得到了一些改進(jìn)。
在UICollectionView 中有一個(gè)固定的類,叫UICollectionViewFlowLayout,iOS已經(jīng)在這個(gè)類中完全支持了self-sizing。為了能開(kāi)啟這一特性,需要我們開(kāi)發(fā)者為一些不能為0的CGSize的cell設(shè)置一下estimated item size。
layout.estimatedItemSize = CGSize(width:50,height:50)
這會(huì)告訴UICollectionView我們想要開(kāi)啟動(dòng)態(tài)計(jì)算內(nèi)容的布局。
至今,我們能有3種方法來(lái)動(dòng)態(tài)的布局。
第一種方法是使用autolayout 當(dāng)我們合理的加上了constrain,當(dāng)cell加載的時(shí)候,就會(huì)根據(jù)內(nèi)容動(dòng)態(tài)的加載布局。
第二種方法,如果你不想使用autolayout的方法,想更加手動(dòng)的控制它,那么我們就需要重寫sizeThatFits()方法。
第三種方法,終極的方法是重寫preferredLayoutAttributesFittingAttributes()方法。在這個(gè)方法里面不僅僅可以提供size的信息,更可以得到alpha和transform的信息。
所以想指定cell的大小,就可以用上面3個(gè)方法之一。
但是實(shí)際操作中,我們可以發(fā)現(xiàn),有時(shí)候設(shè)置一個(gè)合適的estimated item size,對(duì)于我們來(lái)說(shuō)是很困難的事情。如果flow layout可以用數(shù)學(xué)的方法動(dòng)態(tài)的計(jì)算布局,而不是根據(jù)我們給的size去布局,那會(huì)是件很酷的事情。
iOS 10中就引入了新的API來(lái)解決上述的問(wèn)題。
layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
對(duì)于開(kāi)發(fā)者,我們需要做的事情,僅僅就是設(shè)置好flow layout ,然后給estimatedItemSize設(shè)定一個(gè)新的常數(shù), 最后UICollectionViewFlowLayout 就會(huì)自動(dòng)計(jì)算高度了。
系統(tǒng)會(huì)自動(dòng)計(jì)算好所有的布局,包括已經(jīng)定下來(lái)的size的cell,并且還會(huì)動(dòng)態(tài)的給出接下來(lái)cell的大小的預(yù)測(cè)。
接下來(lái)看2個(gè)例子就可以很明顯看出iOS 10針對(duì)self-sizing的改進(jìn)了。
上圖可以看到,iOS 9 的布局是針對(duì)單個(gè)cell計(jì)算的,當(dāng)改變了單個(gè)的cell,其他的cell依舊沒(méi)有變化,還是需要重新計(jì)算。
這里例子就可以很明顯的看出差別了。當(dāng)我們改變了第一個(gè)cell的size以后,系統(tǒng)會(huì)自動(dòng)計(jì)算出所有的cell的size,并且每一行,每一個(gè)section的size都會(huì)被動(dòng)態(tài)的計(jì)算出來(lái),并且刷新界面!
以上就是iOS 10針對(duì)self-sizing的改進(jìn)。
五. Interactive Reordering
談到重新排列,這是我們就需要類比一下UITableView了,UICollectionView的重新排列就如同UITableView 把cell上下移動(dòng),只不過(guò)UITableView的重排是針對(duì)垂直方向的。
在iOS 9中,引入了UICollectionView的Interactive Reordering,在今年的iOS 10中,又加入了一些新的API。
在上圖中,我們可以看到,我們即使任意拖動(dòng)cell,整個(gè)界面也會(huì)重新排列,并且我們改變了cell的大小,整個(gè) UICollectionView 也會(huì)重新動(dòng)態(tài)的布局。
我們先來(lái)看看iOS 9里面的API
class UICollectionView : UIScrollView {
func beginInteractiveMovementForItem(at indexPath: NSIndexPath) -> Bool
func updateInteractiveMovementTargetPosition(_ targetPosition: CGPoint)
func endInteractiveMovement()
func cancelInteractiveMovement()
}
要想開(kāi)啟interactive movement,我們就需要調(diào)用beginInteractiveMovementForItem()方法,其中indexPath代表了我們將要移動(dòng)走的cell。接著每次手勢(shì)的刷新,我們都需要刷新cell的位置,去響應(yīng)我們手指的移動(dòng)操作。這時(shí)我們就需要調(diào)用updateInteractiveMovementTargetPosition()方法。我們通過(guò)手勢(shì)來(lái)傳遞坐標(biāo)的變化。當(dāng)我們移動(dòng)結(jié)束之后,就會(huì)調(diào)用endInteractiveMovement()方法。 UICollectionView 就會(huì)放下cell,處理完整個(gè)layout,此時(shí)你也可以重新刷新model或者處理數(shù)據(jù)model。如果中間突然手勢(shì)取消了,那么這個(gè)時(shí)候就應(yīng)該調(diào)用cancelInteractiveMovement()方法。如果我們重新把cell移動(dòng)一圈之后又放回原位,其實(shí)就是取消了移動(dòng),那這個(gè)時(shí)候就應(yīng)該在cancelInteractiveMovement()方法里面不用去刷新data source。
在iOS 10中,如果你使用UICollectionViewController,那么這個(gè)重排對(duì)于你來(lái)說(shuō)會(huì)更加的簡(jiǎn)單。
class UICollectionViewController : UIViewController {
var installsStandardGestureForInteractiveMovement: Bool
}
你只需要把installsStandardGestureForInteractiveMovement這個(gè)屬性設(shè)置為True即可。CollectionViewController會(huì)自動(dòng)為你加入手勢(shì),并且自動(dòng)為你調(diào)用上面的方法。
以上就是去年iOS 9為我們?cè)黾拥腁PI。
今年的iOS 10新加入的API是在iOS 9的基礎(chǔ)上增加了翻頁(yè)的功能。
UICollectionView繼承自UIScrollView,所以只需要你做的是把isPagingEnabled屬性設(shè)置為True,即可開(kāi)啟分頁(yè)的功能。
collectionView.isPagingEnabled = true
開(kāi)啟分頁(yè)之前:
開(kāi)啟分頁(yè)之后就長(zhǎng)這樣子:
每次移動(dòng)一次就會(huì)以頁(yè)為單位的翻頁(yè)。
六.UIRefreshControl
UIRefreshControl現(xiàn)在可以直接在CollectionView里面使用,同樣的,也可以直接在UITableView里面使用,并且可以脫離UITableViewController。因?yàn)楝F(xiàn)在RefreshControl成為了ScrollView的一個(gè)屬性了。
UIRefreshControl的使用方法很簡(jiǎn)單,就三步:
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(refreshControlDidFire(_:)),
for: .valueChanged)
collectionView.refreshControl = refreshControl
先創(chuàng)建一個(gè)refreshControl,再關(guān)聯(lián)一個(gè)action事件,最后把這個(gè)新的refreshControl賦給想要的控件的對(duì)應(yīng)的屬性即可。
總結(jié)
通過(guò)以上,我們談到了以下的知識(shí):
- UICollectionView cell pre-fetching預(yù)加載機(jī)制
- UICollectionView and UITableView prefetchDataSource 新增的API
- 針對(duì)self-sizing cells 的改進(jìn)
- Interactive reordering
最后,談?wù)勎铱戳薸OS 10 UICollectionView的優(yōu)化的看法吧,原來(lái)有些地方用到AsyncDisplayKit優(yōu)化UICollectionView速度的,現(xiàn)在可以考慮不用第三方庫(kù)優(yōu)化了,系統(tǒng)自帶的方法可以解決一般性的卡頓的問(wèn)題了。我感覺(jué)iOS 10的UICollectionView才像是一個(gè)完整版的,之前的系統(tǒng)優(yōu)化的都不夠。我還是很看好iOS 10的UICollectionView。