Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make sure function runs on main thread only

How can I make sure that my function is run only on the main thread? It updates UI elements.

Is a function like this considered 'bad'?

-(void)updateSomethingOnMainThread {
    if ( ![[NSThread currentThread] isEqual:[NSThread mainThread]] )
        [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
    else {
        // Do stuff on main thread
    }
}

I wrote it like this to avoid having a second function, initially I had it like this:

-(void)updateSomethingOnMainThread_real {
    // Do stuff on main thread
}

-(void)updateSomethingOnMainThread {
    [self performSelectorOnMainThread:@selector(updateSomethingOnMainThread_real) withObject:nil waitUntilDone:NO];
}
like image 210
thelaws Avatar asked Oct 21 '11 16:10

thelaws


3 Answers

As an alternative to ayoy's method-based GCD implementation for guaranteeing execution on the main thread, I use the following GCD-based function in my code (drawn from another answer of mine):

void runOnMainThreadWithoutDeadlocking(void (^block)(void))
{
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}

You can then use this helper function anywhere in your code:

runOnMainThreadWithoutDeadlocking(^{
    // Do stuff that needs to be on the main thread
});

This guarantees that the actions taken in the enclosed block will always run on the main thread, no matter which thread calls this. It adds little code and is fairly explicit as to which code needs to be run on the main thread.

like image 180
Brad Larson Avatar answered Nov 18 '22 14:11

Brad Larson


This is fine. You can also use GCD to execute code on the main thread.

Checkout this SO post.

GCD to perform task in main thread

like image 43
logancautrell Avatar answered Nov 18 '22 14:11

logancautrell


I wrote this simple #define which I've been using with great success:

#define ensureInMainThread(); if (!NSThread.isMainThread) { [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];    return; }

That way your method, assuming it's parameterless, looks like this

- (void) updateTheThings {
      ensureInMainThread();
      [self.dog setTailWag:YES];
      // etc...
like image 6
Dan Rosenstark Avatar answered Nov 18 '22 12:11

Dan Rosenstark