首先说明一下,对着方面,我的理解也不是非常透彻,这是写一写自己的理解.
个人理解(只是个人理解,不知道对不对),每一条线程都有一个runloop,只不过是没有开启,runloop是始终等待命令,runloop是活的,一个程序如果只是死的东西,没有东西监听,有命令也不会执行.
runloop大概意思是程序启动与运转,程序启动就会启动一条线程(在你手动添加多线程的情况先,)而runloop,就是在这一条线程上反复执行线程中的操作.除非你将程序彻底杀死,否则runloop会不断执行这条线上的操作.保持程序始终运行
Runloop的寄生于线程:一个线程只能有唯一对应的runloop.程序运行大概(只是大概)过程:"
启动线程-->runloop将进入-->最高优先级OB创建释放池-->runloop将睡-->最低优先级OB销毁旧池创建新池-->runloop将退出-->最低优先级OB销毁新池-->线程(销毁)"
一个 RunLoop 包含若干个 Mode,每个 Mode 又包含若干个 Source/Timer/Observer。每次调用 RunLoop
的主函数时,只能指定其中一个 Mode,这个Mode被称作 CurrentMode。如果需要切换 Mode,只能退出 Loop,再重新指定一个
Mode 进入。这样做主要是为了分隔开不同组的 Source/Timer/Observer,让其互不影响。
其内部代码整理:
RunLoop事件队列
每次运行run loop,你线程的run loop对会自动处理之前未处理的消息,并通知相关的观察者。具体的顺序如下:
通知观察者run loop已经启动
通知观察者任何即将要开始的定时器
通知观察者任何即将启动的非基于端口的源
启动任何准备好的非基于端口的源
如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤9。
通知观察者线程进入休眠
将线程置于休眠直到任一下面的事件发生:
某一事件到达基于端口的源
定时器启动
Run loop设置的时间已经超时
run loop被显式唤醒
通知观察者线程将被唤醒。
处理未处理的事件
如果用户定义的定时器启动,处理定时器事件并重启run loop。进入步骤2
如果输入源启动,传递相应的消息
如果run loop被显式唤醒而且时间还没超时,重启run loop。进入步骤2
通知观察者run loop结束。
****RunLoopObserver 与 Autorelease Pool****
UIKit通过RunLoopObserver在RunLoop两次Sleep间对AutoreleasePool进行pop和push,将这次Loop中产生的Autorelease对象释放。(好像swift中没有关于释放的问题)
CFRunLoopMode
RunLoop在同一时段只能且必须在一种特定Mode下Run
更换Mode时, 需要暂停当前的Loop,然后重启新的Loop
NSDefalutRunLoopMode 默认状态.空闲状态
UITrackingRunLoopMode 滑动ScrollView
UIInitializationRunLoopMode 私有,App启动时
NSRunLoopCommonModes 默认包括上面第一和第二
UITrackingRunLoopMode 与 NSTimer
默认情况下NSTimer被加入NSDefalutRunLoopMode
如果想NSTimer受到组件或者动画影响 添加到NSRunLoopCommonModes(OC代码如下:)
[[NSRunLoop currentRunLoop]addTimer:timer...forMode:NSRunLoopCommonModes];
swift版代码:
NSRunLoop.currentRunLoop().addTimer(timer,forMode: NSRunLoopCommonModes)
RunLoopMode切换
NSDefaultRunLoopMode->UITrackingRunLoopMode->NSDefalutRunLoopMode
RunLoop的挂起与唤醒
制定用于唤醒的mach_port端口
调用mach_msg监听唤醒端口,被唤醒前,系统内核将这个线程挂起,停留在mach_msg_trap
由另外一个线程(或另一个进程中的某个线程)向内核发送这个端口的msg后,trap状态被唤醒,RunLoop继续开始干活
AFNetWorking 中创建RunLoop
创建一个常驻服务线程的很好方法
[[NSThreadcurrentThread] setName:@"AFNetworking"];NSRunLooprunloop = [NSRunLoopcurrentRunLoop];[runLoop addPort:[NSMachPortport] forMode:NSDefalutRunLoopMode]//一直活着[runLoop run];
swift版代码
varloop= NSRunLoop.currentRunLoop()loop.addPort(NSMachPort(), forMode: NSDefaultRunLoopMode)loop.run()
一个TableView延迟加载图片的新思路
[self.avatarImageView performSelector:@selector(serImage:) withObjetc:downloadedImage afterDelay:0inModes:@[NSDefaultRunLoopMode]] + (NSThread)networkRequestThread {staticNSThread*_networkRequestThread =nil;staticdispatch_once_toncePredicate;dispatch_once(&oncePredicate, ^{ _networkRequestThread = [[NSThreadalloc] initWithTarget:selfselector:@selector(networkRequestThreadEntryPoint:) object:nil]; [_networkRequestThread start]; });return_networkRequestThread;
}
这个代码无法转换成swift,可能是我没想到办法,大家谁找到了请评论,谢谢了。
让Crash的App回光返照 只针对Signal Crash
CFRunLoopRefrunloop =CFRunLoopGetCurrent();NSArrayallModes =CFBridgingRelease(CFRunLoopCopyAllModes(runLoop));while(1){for(NSStringmodeinallModes){CFRunLoopInMode((CFStringRef)mode,0.001,false); }}
**异步测试摘抄**
- (BOOL)runUntilBlock:(BOOL(^)())block timeout:(NSTimeInterval)timeout{
__block Boolean fulfilled =NO;
void(^beforeWaiting) (CFRunLoopObserverRefobserver,CFRunLoopActivityactivity) = ^(CFRunLoopObserverRefobserver,CFRunLoopActivityactivity) {
fulfilled = block();
if(fulfilled) {
CFRunLoopStop(CFRunLoopGetCurrent());
}
};
CFRunLoopObserverRefobserver =CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopBeforeWaiting,true,0, beforeWaiting);
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
//Run!CFRunLoopRunInMode(kCFRunLoopDefaultMode,timeout,false);
CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
CFRelease(observer);
return fulfilled;
}
这一段是摘抄网上帖子 www.cocoachina.com/ios/20150601/11970.html
能力有限,只能写这么多.有什么问题欢迎大家留言指正,我看到一定回复.感谢!!!!!!!
网友评论