参考:http://www.cocoachina.com/ios/20150601/11970.html
1、Timer
- (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];
}
- (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)run
{
NSLog(@"----run");
}
2、Observer
- (void)observer
{
// 创建observer
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
NSLog(@"----监听到RunLoop状态发生改变---%zd", activity);
});
// /* Run Loop 状态监听 */
// typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
// kCFRunLoopEntry = (1UL << 0), //即将进入Loop
// kCFRunLoopBeforeTimers = (1UL << 1),//即将处理Timer
// kCFRunLoopBeforeSources = (1UL << 2),//即将处理Source
// kCFRunLoopBeforeWaiting = (1UL << 5),//即将进入休眠
// kCFRunLoopAfterWaiting = (1UL << 6),//刚从休眠中唤醒
// kCFRunLoopExit = (1UL << 7),//即将退出Loop
// kCFRunLoopAllActivities = 0x0FFFFFFFU
// };
// 添加观察者:监听RunLoop的状态
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
// 释放Observer
/*
CF的内存管理(Core Foundation)
1.凡是带有Create、Copy、Retain等字眼的函数,创建出来的对象,都需要在最后做一次release
* 比如CFRunLoopObserverCreate
2.release函数:CFRelease(对象);
*/
CFRelease(observer);
}
3、应用场景:
-
保住线程的生命(用属性强引用的方式不好使)
#import "ViewController.h"
#import "XMGThread.h"
@interface ViewController ()
/** 线程对象 */
@property (nonatomic, strong) XMGThread *thread;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.thread = [[XMGThread alloc] initWithTarget:self selector:@selector(execute) object:nil];
[self.thread start];
}
- (void)execute
{
NSLog(@"----------execute----%@", [NSThread currentThread]);
//在当前模式添加端口(因为如果当前模式没有东西,RunLoop开启会马上退出)
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
// 启动(run执行首先会判断当前模式有没有东西,如果没有就会退出)
[[NSRunLoop currentRunLoop] run];
//移除
// - (void)removePort:(NSPort *)aPort forMode:(NSRunLoopMode)mode;
NSLog(@"---------");
// 类似于上面的[[NSRunLoop currentRunLoop] run]
// [[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.thread这条线程中的RunLoop添加了Source(有source之后,RunLoop就不会退出了)
[self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:NO];
}
-
在特定模式下执行操作
- (void)useImageView
{
// 只在NSDefaultRunLoopMode模式下显示图片
[self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"placeholder"] afterDelay:3.0 inModes:@[NSDefaultRunLoopMode]];
}
-
子线程添加timer
需将timer手动添加到当前线程的RunLoop并开启,不然不会执行test方法。主线程下默认做了这些操作。
#import "ViewController.h"
#import "XMGThread.h"
@interface ViewController ()
/** 线程对象 */
@property (nonatomic, strong) XMGThread *thread;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.thread = [[XMGThread alloc] initWithTarget:self selector:@selector(execute) object:nil];
[self.thread start];
}
//-(void)execute
//{
// NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:YES];
//添加time到模式
// [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
// [[NSRunLoop currentRunLoop] run];
//}
- (void)execute
{
//scheduledTimerWithTimeInterval创建的time默认会添加到RunLoop默认模式
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] run];
}
4、RunLoop自动释放池什么时候释放?
在RunLoop睡眠之前释放(KCFRunLoopBeforeWaiting)
网友评论