我在iOS中学到了一个全局规则 - >永远不要阻止主线程。 但是,有几次我遇到违反此规则的开源代码片段。
以下是两个例子:
以下功能取自 https://github.com/piwik/piwik-sdk-ios/blob/master/PiwikTracker/PiwikTracker.m
- (void)startDispatchTimer { // Run on main thread run loop __weak typeof(self)weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf stopDispatchTimer]; // If dispatch interval is 0) { // Run on timer weakSelf.dispatchTimer = [NSTimer scheduledTimerWithTimeInterval:weakSelf.dispatchInterval target:weakSelf selector:@selector(dispatch:) userInfo:nil repeats:NO]; NSLog(@"Dispatch timer started with interval %f", weakSelf.dispatchInterval); } }); }
在上面的代码中,我一直试图理解为什么定时器对象需要主线程。像这样的东西不是UI相关的,仍然在主线程上完成。
另一个例子是着名的网络库MKNetworkKit。 以下代码在NSOperation的start方法中。 https://github.com/MugunthKumar/MKNetworkKit/blob/master/MKNetworkKit/MKNetworkOperation.m
dispatch_async(dispatch_get_main_queue(), ^{ self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO]; [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [self.connection start]; });
所以我的问题是为什么人们使用主线程来做没有UI相关的操作,它给了什么好处。如果你没有抓住它,它可能不会冻结你的应用程序,但为什么要抓住机会。
答案 0 :(得分:2)
两个示例都直接或间接使用NSRunLoop方法。在这些情况下,您应该从执行目标NSRunLoop的线程调用方法。因此,您需要dispatch_get_main_queue()。
的Apple文档警告:NSRunLoop类通常不被认为是线程安全的,并且只应在当前线程的上下文中调用其方法。您永远不应该尝试调用在不同线程中运行的NSRunLoop对象的方法,因为这样做可能会导致意外结果。
顺便说一句,NSRunLoop似乎在Core Foundation中使用CFRunLoop,Core Foundation是在Apple的开源许可下发布的。
http://opensource.apple.com/source/CF/CF-855.17/CFRunLoop.c
似乎CFRunLoop是线程安全的(我们可以看到很多__CFRunLoopLock和__CFRunLoopUnlock组合)。但无论如何你最好还是遵守文件:)