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

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

RunLoop_1.png

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

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

Snip20170119_40.png

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

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

  • 第一步添加runloop監(jiān)聽
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ài),我們可以選擇kCFRunLoopBeforeWaiting當(dāng)正要進(jìn)入休眠狀態(tài)時執(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)聽結(jié)果之后回調(diào)的方法,我們可以將需要執(zhí)行的代碼寫到block中,然后加入數(shù)組中,每次runloop執(zhí)行結(jié)束就執(zhí)行一個
static void _runLoopWorkDistributionCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
{
  這里就是我的得到監(jiān)聽結(jié)果之后回調(diào)的方法,我們可以將需要執(zhí)行的代碼寫到block中,然后加入數(shù)組中,每次runloop執(zhí)行結(jié)束就執(zhí)行一個
}

如解釋有誤歡迎指正~

特此鳴謝diwu大神

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

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

typedef BOOL(^MCRunLoopWorkUnit)(void);

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

typedef enum : NSUInteger {
    MCRunLoopDefaultMode = 0,
    MCRunLoopCommonMode
}MCRunlopMode;
/*
 *  初始化
 */
+ (instancetype)sharedRunLoopWork;
/*
 *  監(jiān)聽Runloop的狀態(tài)屬性,默認(rèn)MCRunLoopBeforeWaiting
 */
@property (assign, nonatomic) MCRunLoopFlag runLoopflag;
/*
 *  監(jiān)聽Runloop的模式 
 *  默認(rèn)MCRunLoopDefaultMode(kCFRunLoopDefaultMode) 系統(tǒng)渲染優(yōu)先,當(dāng)系統(tǒng)渲染結(jié)束才能執(zhí)行我們需要的事件
 *  MCRunLoopCommonMode(kCFRunLoopCommonModes) 將timer插入runloop頂層提高優(yōu)先級(使用后切勿將耗時操作加入任務(wù),慎用)
 */
@property (assign, nonatomic) MCRunlopMode runlopMode;
/*
 *  開始監(jiān)聽Runloop
 */
- (void)start;
/*
 *  停止監(jiān)聽Runloop
 */
- (void)stop;
/*
 *  添加需要在Runloop中執(zhí)行的任務(wù)
 */
- (void)addTask:(MCRunLoopWorkUnit)unit withKey:(id)key;
/*
 *  刪除所有的隊列
 */
- (void)removeAllTasks;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Run loop 剖析:Runloop 接收的輸入事件來自兩種不同的源:輸入源(intput source)和定時...
    Mitchell閱讀 12,630評論 17 111
  • Runloop是iOS和OSX開發(fā)中非?;A(chǔ)的一個概念,從概念開始學(xué)習(xí)。 RunLoop的概念 -般說,一個線程一...
    小貓仔閱讀 1,106評論 0 1
  • 前言 最近離職了,可以盡情熬夜寫點總結(jié),不用擔(dān)心第二天上班爽并蛋疼著,這篇的主角 RunLoop 一座大山,涵蓋的...
    zerocc2014閱讀 12,538評論 13 67
  • 這是AF2.x經(jīng)典的代碼: 首先我們要明確一個概念,線程一般都是一次執(zhí)行完任務(wù),就銷毀了。 而添加了runloop...
    有夢想的老伯伯閱讀 2,081評論 5 13
  • runtime 和 runloop 作為一個程序員進(jìn)階是必須的,也是非常重要的, 在面試過程中是經(jīng)常會被問到的, ...
    made_China閱讀 1,269評論 0 7

友情鏈接更多精彩內(nèi)容