Call a model method with a block that will work in the main thread

one of the basic principles of the architecture of my last application is that I am going to call methods in the application model that will be asynchronous and will accept blocks of failure and success script.

ie UI calls a model method with two blocks, one for success and one for failure.

This is great because the context of the original call is preserved, however the block itself is called in the background thread. Is there a way to call a block on the main thread?

I hope I explained this, if not, basically my model methods are asynchronized, return immediately and create a new thread on which op runs. As soon as op returns, I will call the block that will process the returned data, THEN I need to call the block for the success script defined by the callable inside the user interface. However, the success and failure scenario blocks defined in the user interface must be called in the main thread because I need to interact with the user interface elements that should only be executed in the main thread that I trust.

many thanks

+8
objective-c iphone ipad
source share
4 answers

Something like this is probably what you need:

- (void) doSomethingWhichTakesAgesWithArg: (id) theArg resultHandler: (void (^)(BOOL, id, NSError *)) handler { // run in the background, on the default priority queue dispatch_async( dispatch_get_global_queue(0, 0), ^{ id someVar = [theArg computeSomething]; NSError * anError = nil; [someVar transmuteSomehowUsing: self error: &anError]; // call the result handler block on the main queue (ie main thread) dispatch_async( dispatch_get_main_queue(), ^{ // running synchronously on the main thread now -- call the handler handler( (error == nil), theArg, anError ); }); }); } 
+36
source share

If you use a GCD, you can use the "get main queue":

 dispatch_queue_t dispatch_get_main_queue() 

Call this inside an asynchronous send. i.e.

 dispatch_async(dispatch_get_main_queue(), ^{ /* Do somthing here with UIKit here */ }) 

The sample block above can be run in the asynchronous background queue, and the sample code will send the user interface to the main thread.

+10
source share

A similar approach also works with NSOperationQueue :

 NSBlockOperation *aOperation = [NSBlockOperation blockOperationWithBlock:^ { if ( status == FAILURE ) { // Show alert -> make sure it runs on the main thread [[NSOperationQueue mainQueue] addOperationWithBlock:^ { UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Alert" message:@"Your action failed!" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil] autorelease]; [alert show]; }]; } }]; // myAsyncOperationQueue is created somewhere else [myAsyncOperationQueue addOperation:aOperation]; 
+6
source share

NSObject has a method:

 - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait 

Create a method that takes an NSDictionary parameter in a convenient class that will always be around (for example, an application delegate or a single object), package the block and its parameters in an NSDictionary or NSArray and call

 [target performSelectorOnMainThread:@selector(doItSelector) withObject:blockAndParameters waitUntilDone:waitOrNot]; 
+5
source share

All Articles