我已经了解了iOS中的一条全局规则->从不阻塞主线程。但是,有几次我遇到违反此规则的开源代码段。
以下是两个这样的示例:
以下功能来自https://github.com/piwik/piwik-sdk-ios/blob/master/PiwikTracker/PiwikTracker.m
-(void)startDispatchTimer { //在主线程运行循环上运行 __weak typeof(self)weakSelf = self; 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组合)。但是无论如何,您还是最好听从文档:)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句