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];
}
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.
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
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With