观察RunLoop的活动阶段
- (void)observer
{
/**
* 用block创建runloop观察者
*
* CFAllocatorRef allocator 分配器 类型:为创建对象分配内存
* CFOptionFlags activities runloop活动阶段 类型:在Core Foundation中CFOptionFlags是一个针对于特定不透明类型和函数的标志位
* Boolean repeats 是否循环,
* CFIndex order 指定观察者的运行优先级,一般传0
*
*/
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopBeforeTimers, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
NSLog(@"----监听到RunLoop状态发生改变---%zd", activity);
});
/**
* 添加观察者查看runloop的活动
*
* CFRunLoopRef rl 当前要观察的runloop
* CFRunLoopObserverRef observer 观察者
* CFStringRef mode runloop运行的模式
*/
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
// 释放Observer
CFRelease(observer);
/*
CF的内存管理(Core Foundation)
1.凡是带有Create、Copy、Retain等字眼的函数,创建出来的对象,都需要在最后做一次release
* 比如CFRunLoopObserverCreate
2.release函数:CFRelease(对象);
*/
}
定时器
#pragma mark计划调度
- (void)timer2
{
// 调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopMode,如果是在子线程,还需开启runloop
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
// 修改模式
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
#pragma mark普通定时器
- (void)timer
{
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
// 定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
// [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
// 定时器只运行在UITrackingRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
// [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
// 定时器会跑在标记为common modes的模式下
// 标记为common modes的模式:UITrackingRunLoopMode和NSDefaultRunLoopMode
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
图片加载
- (void)useImageView
{
// 只在NSDefaultRunLoopMode模式下显示图片
[self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"placeholder"] afterDelay:3.0 inModes:@[NSDefaultRunLoopMode]];
}
线程常驻
#pragma mark 创建永驻线程
- (void)addThread
{
//创建一条线程去处理任务,当任务结束后,线程进入消亡状态,无法再次开启
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];
}
- (void)run
{
//只需在线程任务中的runloop中添加一个端口,就可以使线程永驻
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
//永远不调用,触发runloop退出
NSLog(@"---------");
}
#pragma mark 利用永驻线程处理其他任务
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:NO];
}
- (void)test
{
NSLog(@"----------test----%@", [NSThread currentThread]);
}
CD定时器
#import "ViewController.h"
@interface ViewController ()
/** 定时器(这里不用带*,因为dispatch_source_t就是个类,内部已经包含了*) */
@property (nonatomic, strong) dispatch_source_t timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
int count = 0;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 获得队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 创建一个定时器(dispatch_source_t本质还是个OC对象)
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
// 设置定时器的各种属性(几时开始任务,每隔多长时间执行一次)
// GCD的时间参数,一般是纳秒(1秒 == 10的9次方纳秒)
// 何时开始执行第一个任务
// dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC) 比当前时间晚1秒
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);
dispatch_source_set_timer(self.timer, start, interval, 0);
// 设置回调
dispatch_source_set_event_handler(self.timer, ^{
NSLog(@"------------%@", [NSThread currentThread]);
count++;
if (count == 4) {
// 取消定时器
dispatch_cancel(self.timer);
self.timer = nil;
}
});
// 启动定时器
dispatch_resume(self.timer);
}