UICollectionView滑動(dòng)流暢性優(yōu)化

UICollectionView滑動(dòng)流暢性優(yōu)化

貴站的圖片支持我真的服了昵骤,要獲得更好的圖片體驗(yàn)請(qǐng)自行百度另一友站的同一標(biāo)題的文章

前言

初始的collection view在滑動(dòng)時(shí)都是十分流暢的畴嘶,然而因?yàn)閏ollection view cell 加載更多的內(nèi)容時(shí)因?yàn)橹骶€程耗用太多性能而導(dǎo)致主線程出現(xiàn)堵塞仅政,導(dǎo)致原本流暢的滑動(dòng)出現(xiàn)卡頓的情況嚼摩。

<center>
<img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="https://raw.githubusercontent.com/MrYu4/MyUploadPicture/master/20190223175348-beginKaDun.gif">


<div style="color:orange; border-bottom: 1px solid #ffffff;
display: inline-block;
color: #000000;
padding: 2px;"></div>
</center>

collection view加載cell時(shí)一般會(huì)常用復(fù)用池磕蛇,所以滑動(dòng)時(shí)每要顯示一個(gè)cell都會(huì)調(diào)用協(xié)議中- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;的方法频敛,而在這方法中除了返回復(fù)用池中的cell霸褒,程序猿還可以趁機(jī)在其中調(diào)用cell自定義的讀取數(shù)據(jù)的方法(姑且稱之為-(void)loadData:)司顿,在本文中即將展示如何將- (void)loadData:中的耗時(shí)操作放入NSOperationQueue中并發(fā)進(jìn)行從而不影響collection view的滑動(dòng)芒粹,同時(shí)在用戶快速滑動(dòng)中,單個(gè)cell的NSOperationQueue中會(huì)堆積大量operation的情況大溜,也將在本文中提出應(yīng)對(duì)方法化漆。

NSOperationQueue和NSInvocationOperation

NSOperationQueue將線程操作以隊(duì)列的形式展現(xiàn),初始化代碼如下:

_queue = ({
            NSOperationQueue *q = [[NSOperationQueue alloc]init];
            //設(shè)置最大并行操作數(shù)為1相當(dāng)于將queue設(shè)置為串行線程
            q.maxConcurrentOperationCount = 1;
            q;
        });

每一個(gè)operation都是這個(gè)隊(duì)列中的一個(gè)元素钦奋,而這個(gè)元素在滿足條件的情況下可以在不用執(zhí)行就從隊(duì)列中移除座云,我們可以利用這種特性來取消其中一些未執(zhí)行但是不必執(zhí)行的operation ,關(guān)鍵代碼如下:

if (self.operationQueue.operationCount >= 2) {
    [self.operationQueue cancelAllOperations];
}
NSInvocationOperation *op = [[NSInvocationOperation alloc]
                initWithTarget:self
                      selector:@selector(operationSelector:)
                        object:dic];
[self.operationQueue addOperation:op];

其中-(void)cancelAllOperations可以讓隊(duì)列里的所有待執(zhí)行的operation移除出隊(duì)列(詳情看官方文檔),要注意付材,如果執(zhí)行此方法時(shí)有operation正在執(zhí)行朦拖,那么那些正在執(zhí)行的operation不會(huì)被強(qiáng)行中止并取消。

Canceling the operations does not automatically remove them from the queue or stop those that are currently executing. For operations that are queued and waiting execution, the queue must still attempt to execute the operation before recognizing that it is canceled and moving it to the finished state.——蘋果官方開發(fā)文檔

NSInvocationOperation是NSOperation的子類厌衔,它和NSBlockOperation一樣都可以作為元素添加到NSOperationQueue中等待執(zhí)行璧帝,最主要的區(qū)別在于前者帶的是@selector后者帶的是block

異步操作中因視圖原因?qū)е鲁绦虮罎r(shí)的應(yīng)對(duì)方法

原本高高興興把耗時(shí)的代碼都放到隊(duì)列中運(yùn)行時(shí)卻發(fā)現(xiàn)在涉及到視圖操作的地方容易出現(xiàn)錯(cuò)亂葵诈,甚至是BAD_XXXX之類的崩潰時(shí)裸弦,就需要檢查@selector中是否包含類似addSubview,removeFromSubview之類的傻X操作(每讀取一次數(shù)據(jù)就把view移出來/放進(jìn)去是什么鬼操作祟同?!View:我來了理疙,我又走了晕城,我來了,我又走了窖贤,你打我呀……)砖顷,遇到這種代碼第一想到的是盡量將其移出Operation,最好是將其放到初始化的方法赃梧,但是還有些情況是有些視圖的屬性受到數(shù)據(jù)的影響滤蝠,需要等耗時(shí)操作結(jié)束之后才能確定視圖的屬性,這個(gè)時(shí)候就要用到GCD的方法了授嘀,如下:

- (void)optimizeOperation:(NSString *)dataStr {
    //模擬十分耗時(shí)間的操作,注意物咳,這里不能放在main_queue里面執(zhí)行,否則時(shí)間還是消耗在了主線程里面
    [NSThread sleepForTimeInterval:0.05];
    if ([dataStr isEqualToString:self.dataStr]) {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.titleLb.text = dataStr;
        });
    }
}

要注意dispatch_async(dispatch_get_main_queue(), ^{})中不要有耗時(shí)的方法蹄皱,我們到目前為止的鋪墊都是為了讓占用主線程的滑動(dòng)操作不要被其他操作堵塞览闰,如果把耗時(shí)操作放進(jìn)去的話就前功盡棄了。

<center>
<img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="https://raw.githubusercontent.com/MrYu4/MyUploadPicture/master/20190223150504-FinalLook.gif">


<div style="color:orange; border-bottom: 1px solid #ffffff;
display: inline-block;
color: #000000;
padding: 2px;">很難想象其中每個(gè)cell的讀取方法中間會(huì)有0.05s的耗時(shí)方法</div>
</center>

附帶demo地址巷折,本文所涉及的思路體現(xiàn)在TextCell.m中:https://github.com/MrYu4/OptimizeCollectionView

可能存在的疑問

  • 可是我就是不想用NSInvocationOperation啊压鉴,我用NSBlockOperation不行嗎?

  • if (self.operationQueue.operationCount >= 2)這個(gè)判斷語句怎么理解锻拘?

隊(duì)列中如果有兩個(gè)或兩個(gè)以上個(gè)待出隊(duì)列的operation油吭,那么第一個(gè)可能是正在執(zhí)行中的,第二個(gè)或者之后都是未執(zhí)行的(忘了說了署拟,queue設(shè)置了最多可并發(fā)運(yùn)行一個(gè)operation)婉宰,這個(gè)時(shí)候正好是有新的operation等待加入,就說明以往的operation沒什么用了芯丧,這個(gè)時(shí)候就可以進(jìn)行剪枝操作芍阎,把operation除去節(jié)省性能世曾。

  • 接著上個(gè)問題缨恒,為什么不是>=1呢

[self.operationQueue cancelAllOperations];能立刻去除的是未執(zhí)行的operation,但正在執(zhí)行的不會(huì)除掉轮听,也就是在cancelAllOperations之前隊(duì)列內(nèi)元素個(gè)數(shù)=1時(shí)骗露,就基本上可以確定隊(duì)列中沒有可以除掉的operation了。

求打賞

<center>
<img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="https://raw.githubusercontent.com/MrYu4/MyUploadPicture/master/20190223153126-merge_from_ofoct%20(1).png">


<div style="color:orange; border-bottom: 1px solid #ffffff;
display: inline-block;
color: #000000;
padding: 2px;"></div>
</center>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末血巍,一起剝皮案震驚了整個(gè)濱河市萧锉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌述寡,老刑警劉巖柿隙,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叶洞,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡禀崖,警方通過查閱死者的電腦和手機(jī)衩辟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來波附,“玉大人艺晴,你說我怎么就攤上這事〉牛” “怎么了封寞?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)仅财。 經(jīng)常有香客問我狈究,道長(zhǎng),這世上最難降的妖魔是什么盏求? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任谦炒,我火速辦了婚禮,結(jié)果婚禮上风喇,老公的妹妹穿的比我還像新娘宁改。我一直安慰自己,他們只是感情好魂莫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布还蹲。 她就那樣靜靜地躺著,像睡著了一般耙考。 火紅的嫁衣襯著肌膚如雪谜喊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天倦始,我揣著相機(jī)與錄音斗遏,去河邊找鬼。 笑死鞋邑,一個(gè)胖子當(dāng)著我的面吹牛诵次,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播枚碗,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼逾一,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了肮雨?” 一聲冷哼從身側(cè)響起遵堵,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后陌宿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锡足,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年壳坪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舱污。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弥虐,死狀恐怖扩灯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情霜瘪,我是刑警寧澤珠插,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站颖对,受9級(jí)特大地震影響捻撑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缤底,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一顾患、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧个唧,春花似錦江解、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至魄梯,卻和暖如春桨螺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酿秸。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工灭翔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辣苏。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓肝箱,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親考润。 傳聞我的和親對(duì)象是個(gè)殘疾皇子狭园,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容