一個(gè)CFRunLoopObserver可以提供一個(gè)回調(diào)函數(shù),使這個(gè)函數(shù)能在Runloop中運(yùn)行。對(duì)比CFRunLoopSource,當(dāng)Runloop中發(fā)生某些事時(shí)(如,sources觸發(fā),runloop進(jìn)入睡眠),CFRunLoopObserver就會(huì)被調(diào)用。 CFRunLoopObserver可以在Runloop中一次或在循環(huán)調(diào)用。
一個(gè)CFRunLoopObserver僅可以注冊(cè)在Runloop中一次,但它可以注冊(cè)在多個(gè)Runloop Mode中。
函數(shù)
CFRunLoopObserverCreateWithHandler
創(chuàng)建一個(gè)基于block回調(diào)的CFRunLoopObserver。
函數(shù)聲明:
CFRunLoopObserverRef??CFRunLoopObserverCreateWithHandler(CFAllocatorRef?allocator,CFOptionFlags?activities,Boolean repeats,CFIndex?order,void(^block)(CFRunLoopObserverRef?observer,CFRunLoopActivity?activity));
參數(shù):
allocator:這個(gè)參數(shù)用來(lái)分配空間給新的對(duì)象。默認(rèn)情況下使用NULL或者kCFAllocatorDefault。
activities:設(shè)置Runloop的運(yùn)行階段的標(biāo)志,當(dāng)運(yùn)行到此階段時(shí),CFRunLoopObserver會(huì)被調(diào)用。具體可看Run Loop Activities。activities其實(shí)是一個(gè)枚舉,這里把它的枚舉類(lèi)型展示出來(lái):
enum ?CFRunLoopActivity{
? ? ?kCFRunLoopEntry=(1<<0),
? ? ?kCFRunLoopBeforeTimers=(1<<1),
? ? ?kCFRunLoopBeforeSources=(1<<2),
? ? ?kCFRunLoopBeforeWaiting=(1<<5),
? ? ?kCFRunLoopAfterWaiting=(1<<6),
? ? ?kCFRunLoopExit=(1<<7),
? ? ?kCFRunLoopAllActivities=0x0FFFFFFFU
? };
typedef ?enumCFRunLoopActivityCFRunLoopActivity;
repeats:CFRunLoopObserver是否循環(huán)調(diào)用,false為單詞調(diào)用,否則循環(huán)調(diào)用。
order:CFRunLoopObserver的優(yōu)先級(jí),當(dāng)在Runloop同一運(yùn)行階段中有多個(gè)CFRunLoopObserver時(shí),根據(jù)這個(gè)來(lái)先后調(diào)用CFRunLoopObserver。正常情況下使用0。
block:回調(diào)的block。
這個(gè)block有兩個(gè)參數(shù):
observer:正在運(yùn)行的run loop observe。
activity:runloop當(dāng)前的運(yùn)行階段。
返回值:
新的CFRunLoopObserver對(duì)象。
詳情:
這個(gè)CFRunLoopObserver不能自動(dòng)添加進(jìn)Runloop中,需使用CFRunLoopAddObserver。
有效:
OS X v10.7及其以后。
個(gè)人解釋一下這個(gè)函數(shù),順便觀察CFRunLoopObserver在Runloop中怎么被調(diào)用的。
CFRunLoopObserver在Runloop的調(diào)用:
1.我們首先在Runloop的源代碼中找到
static int32_t ?__CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle,CFRunLoopModeRef previousMode)
這是Runloo的主循環(huán)函數(shù),Runloop都在這里面運(yùn)行。
然后在這個(gè)函數(shù)里面找到對(duì)CFRunLoopObserver調(diào)用函數(shù):
if(rlm->_observerMask&kCFRunLoopBeforeTimers)__CFRunLoopDoObservers(rl, rlm,kCFRunLoopBeforeTimers);
if(rlm->_observerMask&kCFRunLoopBeforeSources)__CFRunLoopDoObservers(rl, rlm,kCFRunLoopBeforeSources);
我們可以看到從這里進(jìn)去可以看到CFRunLoopObserver的回調(diào)函數(shù)是怎么被調(diào)用的。

我們可以從中看到里面調(diào)用了
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(rlo->_callout, rlo, activity, rlo->_context.info);
再進(jìn)去可以看到

從中可以看到里面調(diào)用了回調(diào)函數(shù),而且這個(gè)回調(diào)函數(shù)的形參是確定的(下面有講這個(gè)回調(diào)函數(shù))?;蛟S我們會(huì)疑惑,這里我們并沒(méi)有回調(diào)block,怎么有block的回調(diào)?那這里我們就要看CFRunLoopObserverCreateWithHandler這個(gè)函數(shù)的源碼了:

我們從中可以看到,這個(gè)函數(shù)內(nèi)部本身還是調(diào)用了CFRunLoopObserverCreate(下面會(huì)講)這個(gè)函數(shù),但它對(duì)回調(diào)函數(shù)進(jìn)行處理(也就是圖中的_runLoopObserverWithBlockContext函數(shù)),使block回調(diào)隱藏在回調(diào)函數(shù)內(nèi)。
創(chuàng)建一個(gè)基于回調(diào)函數(shù)的CFRunLoopObserver。
函數(shù)聲明:
CFRunLoopObserverRef?CFRunLoopObserverCreate(CFAllocatorRef?allocator,CFOptionFlags?activities,Boolean repeats,CFIndex?order,CFRunLoopObserverCallBack?callout,CFRunLoopObserverContext?*context);
相同的參數(shù)可以參考上一個(gè)API函數(shù)的聲明,這里只說(shuō)不一樣的。
context:CFRunLoopObserver結(jié)構(gòu)體里面的一個(gè)結(jié)構(gòu)體,它主要使用來(lái)傳遞消息的,在回調(diào)函數(shù)外面代碼生成的信息可以傳進(jìn)回調(diào)函數(shù)內(nèi)進(jìn)行使用,形成了一個(gè)消息傳遞。在應(yīng)用中,context應(yīng)該是下面那樣的:
CFRunLoopObserverContext ? ?observerContext = {
? ? ? ? ? ? ? ? ? 0,
? ? ? ? ? ? ? ? ?info, //這里填寫(xiě)你要傳遞的信息。
? ? ? ? ? ? ? ? ? &CFRetain,
? ? ? ? ? ? ? ? ? &CFRelease,
? ? ? ? ? ? ? ? ? ?NULL
};
這里不進(jìn)行源碼講解了,沒(méi)什么好講的,源碼的內(nèi)容也是根據(jù)上面的形參對(duì)CFRunLoopObserver的結(jié)構(gòu)體進(jìn)行賦值。
返回一個(gè)布爾值來(lái)查看所檢測(cè)的CFRunLoopObserver是否循環(huán)調(diào)用。
函數(shù)聲明:
BooleanCFRunLoopObserverDoesRepeat(CFRunLoopObserverRef?observer);
嗯。自行體會(huì)吧,沒(méi)什么好說(shuō)的。
CFRunLoopObserverGetActivities
返回所檢測(cè)的CFRunLoopObserver的被運(yùn)行時(shí)的Runloop的運(yùn)行階段。
函數(shù)聲明:
CFOptionFlags?CFRunLoopObserverGetActivities(CFRunLoopObserverRef?observer);
下面的幾個(gè)函數(shù)都是檢測(cè)的CFRunLoopObserver的,沒(méi)啥可說(shuō)的:
作廢一個(gè)在運(yùn)行的CFRunLoopObserver。
函數(shù)聲明:
void CFRunLoopObserverInvalidate(CFRunLoopObserverRef?observer);
檢測(cè)一個(gè)CFRunLoopObserver是否還有效。
函數(shù)聲明:
Boolean CFRunLoopObserverIsValid(CFRunLoopObserverRef?observer);
添加一個(gè)CFRunLoopObserver到一個(gè)run loop mode中。
函數(shù)聲明:
void CFRunLoopAddObserver(CFRunLoopRef?rl,CFRunLoopObserverRef?observer,CFStringRef?mode);
形參:
mode:是一個(gè)字符串,代表Runloop 中的一個(gè)mode,這里展示兩個(gè)常用mode的字符串:
CF_EXPORT const CFStringRef kCFRunLoopDefaultMode;
CF_EXPORT const CFStringRef kCFRunLoopCommonModes;
注意:在添加CFRunLoopObserver后(即這個(gè)函數(shù)后),要用CFRelease函數(shù)釋放掉CFRunLoopObserver。
檢測(cè)一個(gè)run loop mode是否含有CFRunLoopObserver。
函數(shù)聲明:
Boolean CFRunLoopContainsObserver(CFRunLoopRef?rl,?CFRunLoopObserverRef?observer,?CFStringRef?mode);
將一個(gè)CFRunLoopObserver從一個(gè)run loop mode中移除。
void CFRunLoopRemoveObserver(CFRunLoopRef?rl,?CFRunLoopObserverRef?observer,?CFStringRef?mode);
回調(diào)函數(shù)
回調(diào)函數(shù)形式:
typedef void (*CFRunLoopObserverCallBack) (CFRunLoopObserverRef?observer,CFRunLoopActivity?activity,void *info);
形參:
只講info。從上面的源碼可以看出,這個(gè)info是CFRunLoopObserverContext結(jié)構(gòu)體的一個(gè)成員元素,用來(lái)傳遞消息。
數(shù)據(jù)類(lèi)型
兩種:
簡(jiǎn)述它們的關(guān)系:
CFRunLoopObserverRef中含有回調(diào)函數(shù),CFRunLoopObserverContext之類(lèi)的。
CFRunLoopObserverContext含有info,用來(lái)消息傳遞,還包含一些操作函數(shù)。