I have learnt one global rule in iOS -> never to block main thread. However, several time I run into open source code snippets where this rule is violated.
Two such examples are follows :
The following function is taken from 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); } }); }
In the above code I have been trying to understand why is main thread required for timer object. Something like this is not UI related and still done on main thread.
Another example of this is in a famous networking library MKNetworkKit . Where the following code is in start method of NSOperation. 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]; });
So my questions is why do people use main thread for doing no UI related operations and what benefit does it give. It may not freeze your app if you are not holding on to it but why take a chance.
Both examples are using NSRunLoop methods directly or indirectly. In those cases, you should call the methods from the thread which executes the target NSRunLoop. Thus you need dispatch_get_main_queue().
Take a look at the apple document about NSRunLoop https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/classes/nsrunloop_class/reference/reference.html
Warning: The NSRunLoop class is generally not considered to be thread-safe and its methods should only be called within the context of the current thread. You should never try to call the methods of an NSRunLoop object running in a different thread, as doing so might cause unexpected results.
By the way, NSRunLoop seems using CFRunLoop in Core Foundation, and Core Foundation was released under an open source license from Apple.
http://opensource.apple.com/source/CF/CF-855.17/CFRunLoop.c
It seems CFRunLoop is thread-safe (we can see a lot of __CFRunLoopLock and __CFRunLoopUnlock combination). But you would better obey the document anyway :)