I have NSOperationQueue with 3 NSInvocationOperation in a prepareForSegue callback and I need after finishing all async tasks move to another view controller.
How can I be notified about finishing all async tasks and only after this move to another screen?

3 Answers
3

dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
//Code here is executed asynchronously
});
dispatch_group_notify(group, dispatch_get_main_queue(),
^{
//Do something when async has completed
//Note: You are not required to use the main
//queue if you aren't performing any UI work.
});
dispatch_release(group);

I've left a ... in the code because you might want to fill in the object field with something other than nil (but it should not be a UIKit class except those that are documented to be threadsafe).

Alternatively, each operation could return its results via a dispatch_async() or -performSelectorOnMainThread:, but again, it is unwise to reference an instance of a thread-unsafe UIKit class in a block (or as the receiver or object of a -performSelectorOnMainThread:).

There many ways to do this which are specifically mentioned as being thread-unsafe in the GameKit examples — in particular, anything which might end up calling -release on a UIView or UIViewController is dangerous, because that can cause -dealloc to be called on a background thread.