runloop

CFRunLoopObserver 参考(CFRunLoopOb

2016-06-26  本文已影响1997人  酸菜Amour

一个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 Activitiesactivities其实是一个枚举,这里把它的枚举类型展示出来:

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回调隐藏在回调函数内。

CFRunLoopObserverCreate

创建一个基于回调函数的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的结构体进行赋值。


CFRunLoopObserverDoesRepeat

返回一个布尔值来查看所检测的CFRunLoopObserver是否循环调用。

函数声明:

BooleanCFRunLoopObserverDoesRepeat(CFRunLoopObserverRef observer);

嗯。自行体会吧,没什么好说的。

CFRunLoopObserverGetActivities

返回所检测的CFRunLoopObserver的被运行时的Runloop的运行阶段。

函数声明:

CFOptionFlags CFRunLoopObserverGetActivities(CFRunLoopObserverRef observer);

下面的几个函数都是检测的CFRunLoopObserver的,没啥可说的:

CFRunLoopObserverGetContext

CFRunLoopObserverGetOrder

CFRunLoopObserverGetTypeID

CFRunLoopObserverInvalidate

作废一个在运行的CFRunLoopObserver。

函数声明:

void CFRunLoopObserverInvalidate(CFRunLoopObserverRef observer);

CFRunLoopObserverIsValid

检测一个CFRunLoopObserver是否还有效。

函数声明:

Boolean CFRunLoopObserverIsValid(CFRunLoopObserverRef observer);

CFRunLoopAddObserver

添加一个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。

CFRunLoopContainsObserver

检测一个run loop mode是否含有CFRunLoopObserver。

函数声明:

Boolean CFRunLoopContainsObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFStringRef mode);

CFRunLoopRemoveObserver

将一个CFRunLoopObserver从一个run loop mode中移除。

void CFRunLoopRemoveObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFStringRef mode);

回调函数


CFRunLoopObserverCallBack

回调函数形式:

typedef void (*CFRunLoopObserverCallBack) (CFRunLoopObserverRef observer,CFRunLoopActivity activity,void *info);

形参:

只讲info。从上面的源码可以看出,这个info是CFRunLoopObserverContext结构体的一个成员元素,用来传递消息。



数据类型

两种:

CFRunLoopObserverContext

CFRunLoopObserverRef

简述它们的关系:

CFRunLoopObserverRef中含有回调函数,CFRunLoopObserverContext之类的。

CFRunLoopObserverContext含有info,用来消息传递,还包含一些操作函数。

上一篇下一篇

猜你喜欢

热点阅读