我已经了解了iOS中的一项全局规则->从不阻止主线程。
但是,有几次我遇到违反此规则的开源代码段。
以下是两个这样的示例:
以下功能取自
https://github.com/piwik/piwik-sdk-ios/blob/master/PiwikTracker/PiwikTracker.m
-(void)startDispatchTimer {
//在主线程运行循环上运行
__weak typeof(self)weakSelf =自我;
dispatch_async(dispatch_get_main_queue(),^ {
[weakSelf stopDispatchTimer];
//如果调度间隔为0){
//在计时器上运行
weakSelf.dispatchTimer = [NSTimer ScheduledTimerWithTimeInterval:weakSelf.dispatchInterval
目标:弱者
选择器:@选择器(调度:)
userInfo:无
重复:否];
NSLog(@“调度计时器以间隔%f开始,” weakSelf.dispatchInterval);
}
});
}
在上面的代码中,我一直试图理解为什么计时器对象需要主线程。这样的事情与用户界面无关,仍然在主线程上完成。
另一个例子是著名的网络库MKNetworkKit。
NSOperation的启动方法中包含以下代码。
https://github.com/MugunthKumar/MKNetworkKit/blob/master/MKNetworkKit/MKNetworkOperation.m
dispatch_async(dispatch_get_main_queue(),^ {
self.connection = [[NSURLConnection alloc] initWithRequest:self.request
委托人:自己
startImmediately:NO];
[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSRunLoopCommonModes];
[自连接开始];
});
所以我的问题是,为什么人们不使用主线程来执行与UI不相关的操作,以及这样做有什么好处。如果您不坚持使用它,它可能不会冻结您的应用程序,但是为什么要冒险。
最佳答案
这两个示例都直接或间接使用NSRunLoop方法。在这种情况下,您应该从执行目标NSRunLoop的线程中调用方法。因此,您需要dispatch_get_main_queue()。
看看有关NSRunLoop https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/classes/nsrunloop_class/reference/reference.html的苹果文档
警告:NSRunLoop类通常不被认为是线程安全的,并且其方法仅应在当前线程的上下文中调用。您永远不要尝试调用在不同线程中运行的NSRunLoop对象的方法,因为这样做可能会导致意外结果。
顺便说一句,NSRunLoop似乎在Core Foundation中使用CFRunLoop,并且Core Foundation是在Apple的开源许可下发布的。
http://opensource.apple.com/source/CF/CF-855.17/CFRunLoop.c
看来CFRunLoop是线程安全的(我们可以看到很多__CFRunLoopLock和__CFRunLoopUnlock组合)。但是无论如何,您还是最好听从文档:)
关于ios - 何时使用dispatch_get_main_queue,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25795565/