Runloop實(shí)際應(yīng)用中如何優(yōu)化app流暢度

這次主要講的Runloop的實(shí)際應(yīng)用,基礎(chǔ)的內(nèi)容就不在這介紹了,詳細(xì)的文章可以查看深入理解RunLoop

RunLoop_1.png

RunLoop 內(nèi)部的邏輯大致就是上圖的這樣.
主線程中執(zhí)行事件如滑動(dòng)事件觸摸事件等等都在3~5中執(zhí)行,如果我們將其他大量的操作都放其中肯定會(huì)導(dǎo)致界面卡頓.
其實(shí)我們也可以將一些操作放在子線程中,需要渲染時(shí)再回到線程渲染效果也是可以的.

好吧,現(xiàn)在開(kāi)始正式介紹實(shí)現(xiàn)的方法:

Snip20170119_40.png

因?yàn)閞unloop相當(dāng)于一個(gè)while循環(huán)的東西,每當(dāng)事件都處理完之后就進(jìn)入休眠狀態(tài),當(dāng)有新的任務(wù)加入才會(huì)重新喚醒,這就是我們需要利用的地方,runloop進(jìn)入7之后說(shuō)明當(dāng)前所有的事件都已經(jīng)結(jié)束了,所以在這個(gè)時(shí)候執(zhí)行我們的需要的任務(wù)就不會(huì)影響到之前任務(wù)的刷新.
因?yàn)樘O果提供了監(jiān)聽(tīng)runloop狀態(tài)的方法,所以我可以通過(guò)監(jiān)聽(tīng)實(shí)現(xiàn)

具體實(shí)現(xiàn)可以去下載Demo

  • 第一步添加runloop監(jiān)聽(tīng)
static void _registerObserver(CFOptionFlags activities, CFRunLoopObserverRef observer, CFIndex order, CFStringRef mode, void *info, CFRunLoopObserverCallBack callback) {
    CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    CFRunLoopObserverContext context = {
        0,
        info,
        &CFRetain,
        &CFRelease,
        NULL
    };
    observer = CFRunLoopObserverCreate(     NULL,
                                            activities,
                                            YES,
                                            order,
                                            callback,
                                            &context);
    CFRunLoopAddObserver(runLoop, observer, mode);
    CFRelease(observer);
}
  • 蘋果提供了一下的監(jiān)聽(tīng)狀態(tài),我們可以選擇kCFRunLoopBeforeWaiting當(dāng)正要進(jìn)入休眠狀態(tài)時(shí)執(zhí)行,這樣不需要重新喚醒
/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0),
    kCFRunLoopBeforeTimers = (1UL << 1),
    kCFRunLoopBeforeSources = (1UL << 2),
    kCFRunLoopBeforeWaiting = (1UL << 5),
    kCFRunLoopAfterWaiting = (1UL << 6),
    kCFRunLoopExit = (1UL << 7),
    kCFRunLoopAllActivities = 0x0FFFFFFFU
};
  • 這里就是我的得到監(jiān)聽(tīng)結(jié)果之后回調(diào)的方法,我們可以將需要執(zhí)行的代碼寫到block中,然后加入數(shù)組中,每次runloop執(zhí)行結(jié)束就執(zhí)行一個(gè)
static void _runLoopWorkDistributionCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
{
  這里就是我的得到監(jiān)聽(tīng)結(jié)果之后回調(diào)的方法,我們可以將需要執(zhí)行的代碼寫到block中,然后加入數(shù)組中,每次runloop執(zhí)行結(jié)束就執(zhí)行一個(gè)
}

如解釋有誤歡迎指正~

特此鳴謝diwu大神

思路基本照搬大神的Demo,diwu大神的github大神雖然是中國(guó)人但是英文太好,文檔都是英文的,而且demo沒(méi)有寫注解,特地寫了一份帶中文注解的庫(kù),隨帶稍微優(yōu)化了性能大家也可以看看的我優(yōu)化后的庫(kù)喜歡就給個(gè)Star唄
優(yōu)化+注解后的庫(kù):https://github.com/CZXBigBrother/MCRunLoopWork,也保留了原來(lái)的庫(kù)

DWURunLoopWorkDistribution 是大神原來(lái)寫的類
MCRunloopWork 這是我優(yōu)化之后的類,添加了一些方法和配置選項(xiàng),方便在更多場(chǎng)景下使用

typedef BOOL(^MCRunLoopWorkUnit)(void);

typedef enum : NSUInteger {
    MCRunLoopEntry = kCFRunLoopEntry,//進(jìn)入runloop時(shí)
    MCRunLoopBeforeTimers = kCFRunLoopBeforeTimers,//執(zhí)行timer之前時(shí)
    MCRunLoopBeforeSources = kCFRunLoopBeforeSources,//執(zhí)行sources之前時(shí)
    MCRunLoopBeforeWaiting = kCFRunLoopBeforeWaiting,//開(kāi)始waiting之前時(shí)
    MCRunLoopAfterWaiting = kCFRunLoopAfterWaiting,//開(kāi)始waiting之后時(shí)
    MCRunLoopExit = kCFRunLoopExit,//退出runloop時(shí)
    MCRunLoopAllActivities = kCFRunLoopAllActivities//所有的狀態(tài)
}MCRunLoopFlag;//runloop的各種狀態(tài)

typedef enum : NSUInteger {
    MCRunLoopDefaultMode = 0,
    MCRunLoopCommonMode
}MCRunlopMode;
/*
 *  初始化
 */
+ (instancetype)sharedRunLoopWork;
/*
 *  監(jiān)聽(tīng)Runloop的狀態(tài)屬性,默認(rèn)MCRunLoopBeforeWaiting
 */
@property (assign, nonatomic) MCRunLoopFlag runLoopflag;
/*
 *  監(jiān)聽(tīng)Runloop的模式 
 *  默認(rèn)MCRunLoopDefaultMode(kCFRunLoopDefaultMode) 系統(tǒng)渲染優(yōu)先,當(dāng)系統(tǒng)渲染結(jié)束才能執(zhí)行我們需要的事件
 *  MCRunLoopCommonMode(kCFRunLoopCommonModes) 將timer插入runloop頂層提高優(yōu)先級(jí)(使用后切勿將耗時(shí)操作加入任務(wù),慎用)
 */
@property (assign, nonatomic) MCRunlopMode runlopMode;
/*
 *  開(kāi)始監(jiān)聽(tīng)Runloop
 */
- (void)start;
/*
 *  停止監(jiān)聽(tīng)Runloop
 */
- (void)stop;
/*
 *  添加需要在Runloop中執(zhí)行的任務(wù)
 */
- (void)addTask:(MCRunLoopWorkUnit)unit withKey:(id)key;
/*
 *  刪除所有的隊(duì)列
 */
- (void)removeAllTasks;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末氢卡,一起剝皮案震驚了整個(gè)濱河市蜡娶,隨后出現(xiàn)的幾起案子酿傍,更是在濱河造成了極大的恐慌,老刑警劉巖圆裕,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莫杈,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡舔糖,警方通過(guò)查閱死者的電腦和手機(jī)尔破,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門街图,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人懒构,你說(shuō)我怎么就攤上這事餐济。” “怎么了胆剧?”我有些...
    開(kāi)封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵絮姆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我秩霍,道長(zhǎng)篙悯,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任铃绒,我火速辦了婚禮辕近,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匿垄。我一直安慰自己,他們只是感情好归粉,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布椿疗。 她就那樣靜靜地躺著,像睡著了一般糠悼。 火紅的嫁衣襯著肌膚如雪届榄。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天倔喂,我揣著相機(jī)與錄音铝条,去河邊找鬼靖苇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛班缰,可吹牛的內(nèi)容都是我干的贤壁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼埠忘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼脾拆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起莹妒,我...
    開(kāi)封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤名船,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后旨怠,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體渠驼,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年鉴腻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了迷扇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拘哨,死狀恐怖谋梭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情倦青,我是刑警寧澤瓮床,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站产镐,受9級(jí)特大地震影響隘庄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜癣亚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一丑掺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧述雾,春花似錦街州、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至黍翎,卻和暖如春面徽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工趟紊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留氮双,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓霎匈,卻偏偏與公主長(zhǎng)得像戴差,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子唧躲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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

  • Run loop 剖析:Runloop 接收的輸入事件來(lái)自兩種不同的源:輸入源(intput source)和定時(shí)...
    Mitchell閱讀 12,422評(píng)論 17 111
  • Runloop是iOS和OSX開(kāi)發(fā)中非吃焱欤基礎(chǔ)的一個(gè)概念,從概念開(kāi)始學(xué)習(xí)弄痹。 RunLoop的概念 -般說(shuō)饭入,一個(gè)線程一...
    小貓仔閱讀 985評(píng)論 0 1
  • 前言 最近離職了,可以盡情熬夜寫點(diǎn)總結(jié),不用擔(dān)心第二天上班爽并蛋疼著肛真,這篇的主角 RunLoop 一座大山谐丢,涵蓋的...
    zerocc2014閱讀 12,372評(píng)論 13 67
  • 這是AF2.x經(jīng)典的代碼: 首先我們要明確一個(gè)概念历极,線程一般都是一次執(zhí)行完任務(wù)窄瘟,就銷毀了。 而添加了runloop...
    有夢(mèng)想的老伯伯閱讀 1,999評(píng)論 5 13
  • runtime 和 runloop 作為一個(gè)程序員進(jìn)階是必須的趟卸,也是非常重要的蹄葱, 在面試過(guò)程中是經(jīng)常會(huì)被問(wèn)到的, ...
    made_China閱讀 1,203評(píng)論 0 7