CFRunLoopObserver 参考(CFRunLoopOb
一个CFRunLoopObserver可以提供一个回调函数,使这个函数能在Runloop中运行。对比CFRunLoopSource,当Runloop中发生某些事时(如,sources触发,runloop进入睡眠),CFRunLoopObserver就会被调用。 CFRunLoopObserver可以在Runloop中一次或在循环调用。
一个CFRunLoopObserver仅可以注册在Runloop中一次,但它可以注册在多个Runloop Mode中。
函数
CFRunLoopObserverCreateWithHandler
创建一个基于block回调的CFRunLoopObserver。
函数声明:
CFRunLoopObserverRef CFRunLoopObserverCreateWithHandler(CFAllocatorRef allocator,CFOptionFlags activities,Boolean repeats,CFIndex order,void(^block)(CFRunLoopObserverRef observer,CFRunLoopActivity activity));
参数:
allocator:这个参数用来分配空间给新的对象。默认情况下使用NULL或者kCFAllocatorDefault。
activities:设置Runloop的运行阶段的标志,当运行到此阶段时,CFRunLoopObserver会被调用。具体可看Run Loop Activities。activities其实是一个枚举,这里把它的枚举类型展示出来:
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是否循环调用,false为单词调用,否则循环调用。
order:CFRunLoopObserver的优先级,当在Runloop同一运行阶段中有多个CFRunLoopObserver时,根据这个来先后调用CFRunLoopObserver。正常情况下使用0。
block:回调的block。
这个block有两个参数:
observer:正在运行的run loop observe。
activity:runloop当前的运行阶段。
返回值:
新的CFRunLoopObserver对象。
详情:
这个CFRunLoopObserver不能自动添加进Runloop中,需使用CFRunLoopAddObserver。
有效:
OS X v10.7及其以后。
个人解释一下这个函数,顺便观察CFRunLoopObserver在Runloop中怎么被调用的。
CFRunLoopObserver在Runloop的调用:
1.我们首先在Runloop的源代码中找到
static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle,CFRunLoopModeRef previousMode)
这是Runloo的主循环函数,Runloop都在这里面运行。
然后在这个函数里面找到对CFRunLoopObserver调用函数:
if(rlm->_observerMask&kCFRunLoopBeforeTimers)__CFRunLoopDoObservers(rl, rlm,kCFRunLoopBeforeTimers);
if(rlm->_observerMask&kCFRunLoopBeforeSources)__CFRunLoopDoObservers(rl, rlm,kCFRunLoopBeforeSources);
我们可以看到从这里进去可以看到CFRunLoopObserver的回调函数是怎么被调用的。
我们可以从中看到里面调用了
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(rlo->_callout, rlo, activity, rlo->_context.info);
再进去可以看到
从中可以看到里面调用了回调函数,而且这个回调函数的形参是确定的(下面有讲这个回调函数)。或许我们会疑惑,这里我们并没有回调block,怎么有block的回调?那这里我们就要看CFRunLoopObserverCreateWithHandler这个函数的源码了:
我们从中可以看到,这个函数内部本身还是调用了CFRunLoopObserverCreate(下面会讲)这个函数,但它对回调函数进行处理(也就是图中的_runLoopObserverWithBlockContext函数),使block回调隐藏在回调函数内。
创建一个基于回调函数的CFRunLoopObserver。
函数声明:
CFRunLoopObserverRef CFRunLoopObserverCreate(CFAllocatorRef allocator,CFOptionFlags activities,Boolean repeats,CFIndex order,CFRunLoopObserverCallBack callout,CFRunLoopObserverContext *context);
相同的参数可以参考上一个API函数的声明,这里只说不一样的。
context:CFRunLoopObserver结构体里面的一个结构体,它主要使用来传递消息的,在回调函数外面代码生成的信息可以传进回调函数内进行使用,形成了一个消息传递。在应用中,context应该是下面那样的:
CFRunLoopObserverContext observerContext = {
0,
info, //这里填写你要传递的信息。
&CFRetain,
&CFRelease,
NULL
};
这里不进行源码讲解了,没什么好讲的,源码的内容也是根据上面的形参对CFRunLoopObserver的结构体进行赋值。
返回一个布尔值来查看所检测的CFRunLoopObserver是否循环调用。
函数声明:
BooleanCFRunLoopObserverDoesRepeat(CFRunLoopObserverRef observer);
嗯。自行体会吧,没什么好说的。
CFRunLoopObserverGetActivities
返回所检测的CFRunLoopObserver的被运行时的Runloop的运行阶段。
函数声明:
CFOptionFlags CFRunLoopObserverGetActivities(CFRunLoopObserverRef observer);
下面的几个函数都是检测的CFRunLoopObserver的,没啥可说的:
作废一个在运行的CFRunLoopObserver。
函数声明:
void CFRunLoopObserverInvalidate(CFRunLoopObserverRef observer);
检测一个CFRunLoopObserver是否还有效。
函数声明:
Boolean CFRunLoopObserverIsValid(CFRunLoopObserverRef observer);
添加一个CFRunLoopObserver到一个run loop mode中。
函数声明:
void CFRunLoopAddObserver(CFRunLoopRef rl,CFRunLoopObserverRef observer,CFStringRef mode);
形参:
mode:是一个字符串,代表Runloop 中的一个mode,这里展示两个常用mode的字符串:
CF_EXPORT const CFStringRef kCFRunLoopDefaultMode;
CF_EXPORT const CFStringRef kCFRunLoopCommonModes;
注意:在添加CFRunLoopObserver后(即这个函数后),要用CFRelease函数释放掉CFRunLoopObserver。
检测一个run loop mode是否含有CFRunLoopObserver。
函数声明:
Boolean CFRunLoopContainsObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFStringRef mode);
将一个CFRunLoopObserver从一个run loop mode中移除。
void CFRunLoopRemoveObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFStringRef mode);
回调函数
回调函数形式:
typedef void (*CFRunLoopObserverCallBack) (CFRunLoopObserverRef observer,CFRunLoopActivity activity,void *info);
形参:
只讲info。从上面的源码可以看出,这个info是CFRunLoopObserverContext结构体的一个成员元素,用来传递消息。
数据类型
两种:
简述它们的关系:
CFRunLoopObserverRef中含有回调函数,CFRunLoopObserverContext之类的。
CFRunLoopObserverContext含有info,用来消息传递,还包含一些操作函数。