1.RunLoop概念
是一個讓線程能隨時處理事件但是不退出的機制多矮,它是一個對象耙册,這個對象管理了其需要處理的事件和消息,并且提供了一個入口函數(shù),線程執(zhí)行了這個函數(shù)以后躏吊,就會處于這個函數(shù)內(nèi)部 接收消息,等待赤屋,處理的循環(huán)中园骆,這個這個循環(huán)結(jié)束,函數(shù)返回津滞。
2.RunLoop與線程的關系
蘋果不允許直接創(chuàng)建 RunLoop铝侵,它只提供了兩個自動獲取的函數(shù):CFRunLoopGetMain() 和 CFRunLoopGetCurrent()。
可以看出触徐,線程和RunLoop是一一對應的咪鲜,其關系是保存在一個全局的Dictionary中,線程創(chuàng)建的時候沒有RunLoop撞鹉,你如果不獲取疟丙,它就一直沒有,RunLoop的創(chuàng)建是在第一次獲取的時候孔祸,RunLoop的銷毀是在線程結(jié)束的時候隆敢,所以你只能在一個線程內(nèi)部獲取其RunLoop(主線程除外)
3.RunLoop 的 Mode
蘋果公開提供的 Mode 有兩個:
1 NSDefaultRunLoopMode(kCFRunLoopDefaultMode)默認,空閑狀態(tài)
2 UITrackingRunLoopMode ScrollView滑動時
同時蘋果還提供了一個操作 Common 標記的字符串:kCFRunLoopCommonModes (NSRunLoopCommonModes)崔慧,你可以用這個字符串來操作 Common Items拂蝎,或標記一個 Mode 為 “Common”。使用時注意區(qū)分這個字符串和其他 mode name
RunLoop其內(nèi)部是一個 do-while 循環(huán)惶室。當你調(diào)用 CFRunLoopRun() 時温自,線程就會一直停留在這個循環(huán)里;直到超時或被手動停止皇钞,該函數(shù)才會返回悼泌。
4.AFNetworking
+ (void)networkRequestThreadEntryPoint:(id)__unused object {
@autoreleasepool {
[[NSThread currentThread] setName:@"AFNetworking"];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}
+ (NSThread *)networkRequestThread {
static NSThread *_networkRequestThread = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
[_networkRequestThread start];
});
return _networkRequestThread;
}
RunLoop 啟動前內(nèi)部必須要有至少一個 Timer/Observer/Source,所以 AFNetworking 在 [runLoop run] 之前先創(chuàng)建了一個新的 NSMachPort 添加進去了夹界。通常情況下馆里,調(diào)用者需要持有這個 NSMachPort (mach_port) 并在外部線程通過這個 port 發(fā)送消息到 loop 內(nèi);但此處添加 port 只是為了讓 RunLoop 不至于退出,并沒有用于實際的發(fā)送消息鸠踪。
- (void)start {
[self.lock lock];
if ([self isCancelled]) {
[self performSelector:@selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
} else if ([self isReady]) {
self.state = AFOperationExecutingState;
[self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
}
[self.lock unlock];
}
當需要這個后臺線程執(zhí)行任務時丙者,AFNetworking 通過調(diào)用 [NSObject performSelector:onThread:..] 將這個任務扔到了后臺線程的 RunLoop 中。
保持RunLoop不退出的方法啟動前內(nèi)部必須要有至少一個 Timer/Observer/Source营密,AFNetworking中是持有一個NSMachPort械媒,而SRWebSocket中是用dispatch_group_wait和dispatch_group_leave,單獨創(chuàng)建一個NSRunLoop的分類