iOS学习笔记-138.RunLoop06——Runloop相关类4_ CFRunloopSourceRef和CFRunLoopObserverRef

RunLoop06——Runloop相关类4_ CFRunloopSourceRef和CFRunLoopObserverRef

一、CFRunloopSourceRef

1.是事件源也就是输入源,有两种分类模式;

一种是按照苹果官方文档进行划分的

另一种是基于函数的调用栈来进行划分的(source0和source1)。

2.具体的分类情况

(1)以前的分法

Port-Based Sources

Custom Input Sources

Cocoa Perform Selector Sources

(2)现在的分法

Source0:非基于Port的(用户主动出发的)

Source1:基于Port的(系统内部的消息事件)

3.可以通过打断点的方式查看一个方法的函数调用栈


二、CFRunLoopObserverRef

CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变

2.1 如何监听

//创建一个runloop监听者
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(),kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {

    NSLog(@"监听runloop状态改变---%zd",activity);
});

//为runloop添加一个监听者
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);

CFRelease(observer);

2.2 代码示例

//
//  ViewController.m
//  03_UIView93_ CFRunloopObserverRef和CFRunloopSourceRef
//
//  Created by 杞文明 on 17/9/11.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@end

@implementation ViewController

-(void)viewDidLoad{
    [self observerCreate];
}

- (IBAction)btnClick:(id)sender {
    NSLog(@"----%s",__func__);
}

-(void)observerCreate{
    //1.创建监听者
    /*
      第一个参数:怎么分配存储空间
      第二个参数:要监听的状态 。kCFRunLoopAllActivities 所有的状态
      第三个参数:是否持续监听
      第四个参数:优先级 总是传0
      第五个参数:当状态改变时候的回调
      */
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        switch (activity) {
            case kCFRunLoopEntry:
                NSLog(@"即将进入runloop");
                break;
            case kCFRunLoopBeforeTimers:
                NSLog(@"即将处理timer事件");
                break;
            case kCFRunLoopBeforeSources:
                NSLog(@"即将处理source事件");
                break;
            case kCFRunLoopBeforeWaiting:
                NSLog(@"即将进入睡眠");
                break;
            case kCFRunLoopAfterWaiting:
                NSLog(@"被唤醒");
                break;
            case kCFRunLoopExit:
                NSLog(@"runloop退出");
                break;

            default:
                break;
        }
    });

    //2.添加监听者
    /*
       第一个参数:要监听哪个runloop
       第二个参数:观察者
       第三个参数:运行模式
       */
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
}

@end

2.3 CFRunLoopActivity

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0),           即将进入runloop
    kCFRunLoopBeforeTimers = (1UL << 1),    即将处理timer事件
    kCFRunLoopBeforeSources = (1UL << 2),   即将处理source事件
    kCFRunLoopBeforeWaiting = (1UL << 5),   即将进入睡眠
    kCFRunLoopAfterWaiting = (1UL << 6),    被唤醒
    kCFRunLoopExit = (1UL << 7),            runloop退出
    kCFRunLoopAllActivities = 0x0FFFFFFFU
};

2.4 图示

image

2.5 运行结果

[74454:384907] 被唤醒
[74454:384907] 即将处理timer事件
[74454:384907] 即将处理source事件
[74454:384907] 即将处理timer事件
[74454:384907] 即将处理source事件
[74454:384907] 即将处理timer事件
[74454:384907] 即将处理source事件
[74454:384907] 即将处理timer事件
[74454:384907] 即将处理source事件
[74454:384907] 即将进入睡眠
[74454:384907] 被唤醒
[74454:384907] 即将处理timer事件
[74454:384907] 即将处理source事件
[74454:384907] 即将处理timer事件
[74454:384907] 即将处理source事件
[74454:384907] -----[ViewController btnClick:]
[74454:384907] 即将处理timer事件
[74454:384907] 即将处理source事件
[74454:384907] 即将进入睡眠
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Runloop的工作:如何管理事件/消息,如何让线程在没有处理消息时休眠以避免资源占用、在有消息到来时立刻被唤醒。 Osx/ios提供了两种runloop对象 : CFRunLoopRef是在CoreFoundation框架呢,是纯C函数的API,是线程安全的 NSRunLoop是基于CFRunLoopRef的封装,不是线程安全 CFRunLoopRef的线程安全性:CFRunLoopRef不是在线程刚创建的时候创建的,而是在线程获取的时候创建的,如果不主动获取线程,一直不会有。CFRunLoopRef在创建时通过static CFSpinLock_t loopsLock锁住CFRunLoopRef对象,所以CFRunLoopRef是安全的。 一个runloop包含若干个mode。每个mode又包含若干个Source/Timer/Observer CFRunLoopSourceRef是事件产生的地方。Source有两个版本: Source0和Source1。 Source0只包含一个回调,它不能主动出发事件,需要调用CFRunLoopSOurceSignal(source)将source标记,然后手动调用CFRunloopWakeUp()来唤醒RunLoop Source1包含了一个mach_port和一个回调,被用于通过内核和其他线程来发送消息,这种source能主动唤醒runloop。 CFRunLoopTimerRef是基于时间的触发器,它和NSTimer是toll-free bridged的,可以混用,包含一个时间长度和一个回调。当其加入到RunLoop时,RunLoop会注册对应的时间点,当时间点到时,RunLoop会被唤醒执行回调。 CFRunLoopObserverRef是观察者,每个Observer都包含了一个回调,当RunLoop的状态发生变化时,观察者就能通过回调接受到这个变化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值