博客> RunLoop的基本用法
RunLoop的基本用法
2018-11-14 08:31 评论:0 阅读:1210 狂奔的蜗牛102
ios Runloop 定时器 NSTimer

定时器(NSTimer)

-(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];
//一个RunLoop下有多个模式,但是它只能运行在一个模式下,要想在另外一个模式下运行,必须先退出当前循环,切换到另一个模式

}

-(void)timer2 { // 调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopMode NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];

// 修改模式
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

}

创建观察者(Observer),监听监听RunLoop的状态

//看 observer 方法里的打印,你会发现 CFRunLoopObserverRef 的运行机理 -(void)observer { // 创建observer,监听RunLoop的状态 CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { NSLog(@"----监听到RunLoop状态发生改变---%zd", activity); //如果不做任何操作,这个打印一会就不打印了,线程睡觉了(休眠) //如果想在按钮点击之前做一些事情,可以在 activity= 4时处理 });

// 添加观察者:监听RunLoop的状态
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);

// 释放Observer
CFRelease(observer);

}

现在ARC模式开发,我们创建的OC对象,不需要我们管理内存释放,
CF的内存管理(Core Foundation),不是OC对象,是C语言层面的东西,不受ARC控制
- 凡是带有Create、Copy、Retain等字眼的函数,创建出来的对象,都需要在最后做一次release
 比如CFRunLoopObserverCreate
  • release函数:CFRelease(对象);

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {

kCFRunLoopEntry = (1UL <&lt; 0), //即将进入Loop   //1

kCFRunLoopBeforeTimers = (1UL <&lt; 1),//即将处理Timer   //2

kCFRunLoopBeforeSources = (1UL <&lt; 2),//即将处理Source  //4

kCFRunLoopBeforeWaiting = (1UL <&lt; 5),//即将进入休眠  //32

kCFRunLoopAfterWaiting = (1UL <&lt; 6),//刚从休眠中唤醒   //64

kCFRunLoopExit = (1UL <&lt; 7),//即将推出Loop  //128

kCFRunLoopAllActivities = 0x0FFFFFFFU

};

图片的显示

/ 有时我们正在滚动tableView上,会把图片显示出来,但是图片如果比较大,就会渲染,渲染就会比较耗时。 在ScrollView滑动时展示一堆图片,可能会有点卡,有些人可能会推迟显示 1:监听ScrollView的滚动,当手松开,ScrollView停止滚动时,让图片显示出来 / //2: 只在NSDefaultRunLoopMode模式下显示图片,滑动停止时,才会显示图片 [self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"placeholder"] afterDelay:3.0 inModes:@[NSDefaultRunLoopMode]];

常驻线程

-(void)viewDidLoad{

self.thread = [[XMGThread alloc] initWithTarget:self selector:@selector(run) object:nil]; [self.thread start];

}

-(void)run{ NSLog(@"----------run----%@", [NSThread currentThread]); //addPort 相当于添加了 source [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run]; // 调用run方法,其实 和下面俩句话差不多 NSLog(@"---------"); // [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; // [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]]; //一个子线程,一直在后台监听用户的某些行为 //线程一旦消亡,就不能重新在开启, }

-(void)test{ NSLog(@"----------test----%@", [NSThread currentThread]); }

-(void)touchesBegan:(NSSet )touches withEvent:(UIEvent )event{ [self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:NO]; } //看打印,则可以看到 在self.thread 里,这个线程一直没有死掉

tip

一、什么是RunLoop

  1. 从字面意思看,运行循环,跑圈;

  2. 其实它内部就是do-while循环,在这个循环内部不断地处理各种任务(比如 Source,Timer,Observer)`

  3. 一个线程对应一个RunLoop,主线程的RunLoop默认已经启动,子线程的RunLoop得手动启动(调用run方法);

4.RunLoop只能选择一个Model启动,如果当前Model中没有任何Source、Timer、Observer,那么就直接退出

二、 你在开发过程中怎么使用RunLoop

1.开启常驻线程(让一个子线程不进入消亡状态,等待其他线程发来消息,处理其他事件)

*在子线程中开启一个定时器

*在子线程中长期监控一些行为(在子线程中进行一些长期监控)

2.可以控制定时器在特定模式下运行

3.可以让某些事件(行为、任务)在特定模式下执行.eg: performSelector方法

4.可以添加Oberver监听RunLoop的状态,比如监听点击事件的处理(在所有点击事件之前做一些事情)

5.自动释放池什么时候释放:在RunLoop睡眠之前释放(kCFRunLoopBeforeWaiting)

RunLoop应用的demo

https://github.com/WoNiu361/runLoop

后记

后续会持续更新

收藏
2
sina weixin mail 回到顶部