作用:
Runloop的本质是线程的“经纪人”,专门给线程找事干。
是一个死循环,保持线程活着,有活干活,没活休眠。而不会让一个线程一个任务执行完了,马上释放掉。
Runloop里面维护了一个消息队列,用于存放线程要干的活。活分为很多种,也就是下面将要提到的事件源。
基于事件驱动的应用,都会有一个类似的runloop机制,这个区别于基于命令的程序。这套机制与平台无关,与业务机制相关。
创建:
主线程的runloop由系统创建,子线程的runloop的创建方式如下(参考AFNetworking)。
NSRunLoop*runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPortport]forMode:NSDefaultRunLoopMode];
[runLoop run];
Runloop能够接受的事件源:
1,NSTimer事件。CADisplayLink事件,类似timer的一种机制,屏幕每刷新一帧,触发一次执行。
2,UIEvent:iOS支持三种事件,触摸事件,运动事件,远程控制事件,通过source0触发。
3,NSObject(NSDelayedPerforming)
----NSRunLoop.h
@interfaceNSObject (NSDelayedPerforming)
- (void)performSelector:(SEL)aSelector withObject:(nullableid)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;
- (void)performSelector:(SEL)aSelector withObject:(nullableid)anArgument afterDelay:(NSTimeInterval)delay;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(nullableid)anArgument;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;
@end
4,NSObject(NSThreadPerformAddition)
---NSThread.h
@interfaceNSObject (NSThreadPerformAdditions)
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullableid)arg waitUntilDone:(BOOL)wait modes:(nullableNSArray *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullableid)arg waitUntilDone:(BOOL)wait;
// equivalent to the first method with kCFRunLoopCommonModes
- (void)performSelector:(SEL)aSelector onThread:(NSThread*)thr withObject:(nullableid)arg waitUntilDone:(BOOL)wait modes:(nullableNSArray *)arrayNS_AVAILABLE(10_5,2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread*)thr withObject:(nullableid)arg waitUntilDone:(BOOL)waitNS_AVAILABLE(10_5,2_0);
// equivalent to the first method with kCFRunLoopCommonModes
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullableid)argNS_AVAILABLE(10_5,2_0);
@end
5,NSUrlConnection。回调事件在主线程的RunLoop中。
6,其他:autorelease对象释放,动画(CATransition,CAAnimation),NSPort,dispatch_get_main_queue()。
Runloop起作用举例,如点击事件。
CFRunLoopSource:
Source0,app内部事件,如触摸事件等等
Source1,进程通信事件。
NSTimer----CFRunLoopTimer;
GCD也有延迟执行的接口,这个延迟执行,据说跟Timer的机制不一样。只有GCD中在mainQueue中block的执行与RunLoop有关系。
performSelector是基于runLoop的,因此如果在子线程中,子线程没有开启runLoop,则调用方法不会生效。
GCD的延迟执行的函数,不是基于RunLoop的,因此不担心子线程调用的问题。
GCD里面延迟操作的逻辑,并不是基于Timer的。
Core Fundation部分开源的代码。
http://opensource.apple.com/source/CF/CF-855.14/
http://opensource.apple.com/source/CF/CF-855.17/