Imagine that I have a view with some UIKit object as its subview (for example, UIActivityIndicatorView – this doesn’t matter). This view also has a selector, called doSomething, which somehow manages UIKit object (in our example it can start or stop indicator view).
I create NSInvocationOperation (from view’s code parts) with initWithTarget:self selector:@selector(doSomething) object:nil. Then add it to NSOperationQueue. And all works fine.
How?! It should be a new thread and non-thread-safe UIKit object! Why no error found (and no crash happened)?
The
NSInvocationOperationclass is a concrete subclass ofNSOperationthat implements a non-concurrent operation.In a non-concurrent operation, the operation’s task is performed synchronously—that is, the operation object does not create a separate thread on which to run the task. Thus, when the
startmethod of a non-concurrent operation is called, the operation executes immediately in the current thread. By the time thestartmethod of such an object returns control to the caller, the task itself is complete.However, using
NSOperationQueuechanges this behavior. NSOperationQueue always executes operations concurrently; a non-concurrent operation requires a separate thread in order to execute concurrently, andNSOperationQueueprovides this thread.This means that if you’d execute your
NSInvocationOperationdirectly, you’d be able to access your UIKit object thread-safe(the operation would run o the same thread). In your case, if using aNSOperationQueue, you should schedule the work that uses the UIKit object on the main thread, using NSObject’s performSelectorOnMainThread:withObject:waitUntilDone: from your invocation selector.