RunLoop 应用:NSTimer、 PerformSelector、常驻线程
iOS 中有两套API访问 Foundation(NSRunLoop), CoreFoundation CFRunLoopRef
主线程
**相关联的RunLoopint main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
int main(int argc, char * argv[]) {
@autoreleasepool {
// 查看了UIApplicationMain 的返回值是int类型
// UIKIT_EXTERN int UIApplicationMain(int argc, char *argv[], NSString * __nullable principalClassName, NSString * __nullable delegateClassName);
NSLog(@"welcome to Runloop");
int jjTest = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
NSLog(@"快到这里来");
return jjTest;
}
}
一个唯一的
与之对应的RunLoop对象我的天该怎么看:JJ看到的貌似是一些CFRunLoopObserver CFRunLoopSource, 还有timers 等对象,打印出来发现还是有些复杂了,what should i do~
那就只能看看官方文档有关RunLoop的描述了,如果英文不好的就继续往下
根据文档的描述:RunLoop相关联的类有五个(再看看打印出来的内容)
RunLoop 中对象
1.从上图可以看出
Source
/Observer
/Timer
CFRunLoopModeRef 一共有五种模式
CFRunLoopSourceRef(函数调用栈)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"-------");
}
CFRunLoopTimerRef:基于时间的触发器(和NSTimer差不多)
CFRunLoopObserverRef:监听RunLoop状态的观察者
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0), // 1
kCFRunLoopBeforeTimers = (1UL << 1), // 2
kCFRunLoopBeforeSources = (1UL << 2), // 4
kCFRunLoopBeforeWaiting = (1UL << 5), // 32
kCFRunLoopAfterWaiting = (1UL << 6), // 64
kCFRunLoopExit = (1UL << 7), // 128
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
监听RunLoop:监听RunLoop的状态 用途:在RunLoop唤醒前做些操作
// 创建observer
CFRunLoopObserverRef obser = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
NSLog(@"-----Runloop状态------%zd", activity);
});
// 添加观察者:监听RunLoop的状态
CFRunLoopAddObserver(CFRunLoopGetMain(), obser, kCFRunLoopDefaultMode);
// 释放Observer
CFRelease(obser);
在RunLoop中创建定时器:
NSTimer *timer =[NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(JYTest) userInfo:nil repeats:YES];
// 定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
// [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
// 定时器只运行在UITrackingRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
// [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
// 标记为common modes的模式:UITrackingRunLoopMode和NSDefaultRunLoopMode
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
- 定时器NSTimer的创建方式二:scheduledTimerWithTimeInterval
- 创建timer:此方法是自动将timer 添加到线程中
- 注意NSTimer 在`子线程创建timer` 需要手动开启当前线程的RunLoop
```objc
- (void)scheduledTimer {
// 调用了
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(JYTest) userInfo:nil repeats:YES];
// 改变Timer的模式调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopMode
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
- (void) JYTest {
NSLog(@"----0 0 ");
}
需求一 开辟一个不死线程来处理自定义的一些事件(常驻线程)
创建一个不死线程:
JJThread
,并重写dealloc 方法// 将线程定义成属性
@property (nonatomic, strong) JJThread *thread;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.thread = [[JJThread alloc] initWithTarget:self selector:@selector(jjTest) object:nil];
[self.thread start];
}
- (void)jjTest {
// NSRunloop 中必须要有timer, source, observer 一个或者多个,不然会导致
NSLog(@"-----jjTest-------%@", [NSThread currentThread]);
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
NSLog(@"-----jjTest-------%@", [NSThread currentThread]);
// http://stackoverflow.com/questions/31199802/what-does-nsrunloop-currentrunloop-runmodensdefaultrunloopmode-beforedate
}
创建RunLoop,方式二
- (void)jjTest {
NSLog(@"----------run----%@", [NSThread currentThread]);
while (1) {
[[NSRunLoop currentRunLoop] run];
}
}
- (void)jjRun {
NSLog(@"------jjRun------%@", [NSThread currentThread]);
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self performSelector:@selector(jjRun) onThread:self.thread withObject:nil waitUntilDone:NO];
}