原文地址:http://www.cocoachina.com/ios/20160706/16952.html
前言
關(guān)于 iOS 10 UICollectionView的新特性揍愁,主要還是體現(xiàn)在如下3個(gè)方面
-
順滑的滑動(dòng)體驗(yàn)
現(xiàn)在基本上人人都離不開手機(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í)際開發(fā)app中,cell會(huì)比這復(fù)雜很多仇让。 我們先生成100個(gè)cell。當(dāng)用戶滑動(dòng)不是很快的時(shí)候躺翻,還感覺不出來(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了你画。要想用戶感覺不到卡頓,那么我們的app必須幀率達(dá)到60幀/秒桃漾。用數(shù)學(xué)換算一下就是每幀16毫秒就必須刷新一次坏匪。
我們用圖標(biāo)來(lái)分析一下掉幀的問(wèn)題。下面會(huì)出現(xiàn)2種不同的幀撬统。
- 1.第一種情況适滓,下圖是當(dāng)用戶輕微的上下小幅度滑動(dòng)。這個(gè)時(shí)候每個(gè)cell的加載壓力都不大恋追,iOS針對(duì)這種情況凭迹,已經(jīng)做了很好的優(yōu)化了,所以用戶感覺不到任何卡頓苦囱。這種情況是不會(huì)掉幀嗅绸,用戶也希望能使用如此順滑的app。
- 2.第二種情況撕彤,當(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í)間里面去倒谷。這種情況下,用戶就感覺到了卡頓了糙箍。
我們換種方式在說(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è)方法里面就是我們開發(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完全離開屏幕之后贺纲,就會(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還沒有進(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à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的可見區(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完全沒有加一行代碼′塘保現(xiàn)在iOS 10是絲滑的滑動(dòng)體驗(yàn)實(shí)在是太棒了F床浴!
二. 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都不是從重用隊(duì)列里面拿出來(lái)的杖虾。
如果這個(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)看看從文章開始到現(xiàn)在,UICollectionView的性能提升了多少窑滞。我們還是用掉幀的方法來(lái)看看UICollectionView的性能琼牧。
上圖是iOS 9 UICollectionView的性能,很明顯的看見哀卫,波峰波谷很明顯巨坊,并且還掉了8幀,有明顯的卡頓現(xiàn)象此改。
上圖是iOS 10 UICollectionView的性能趾撵,我們可以很明顯的看到,經(jīng)過(guò)iOS 10的優(yōu)化共啃,整個(gè)曲線很明顯平緩了一些占调,沒有極端的波峰掉幀現(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)該開啟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ù)字,順序就是列表上可見的順序稼虎。第二個(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猿推。為了能開啟這一特性,需要我們開發(fā)者為一些不能為0的CGSize的cell設(shè)置一下estimated item size捌肴。
layout.estimatedItemSize = CGSize(width:50,height:50)
這會(huì)告訴UICollectionView我們想要開啟動(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ì)于開發(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依舊沒有變化裆泳,還是需要重新計(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()
}
要想開啟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为迈,即可開啟分頁(yè)的功能三椿。
collectionView.isPagingEnabled = **true**
開啟分頁(yè)之前:
開啟分頁(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)題了镜粤。我感覺iOS 10的UICollectionView才像是一個(gè)完整版的,之前的系統(tǒng)優(yōu)化的都不夠玻褪。我還是很看好iOS 10的UICollectionView肉渴。