6

I am trying to perform this action on the main thread:

[curItem.mButton setBackgroundImage:newArt forState:UIControlStateNormal];

So I do this...

cWrapperObject* obj = [cWrapperObject alloc];
[obj setupParams :curItem.mButton :newArt];
[obj performSelectorOnMainThread:@selector(setImageForButton) withObject:nil waitUntilDone:YES];

I feel like this is bad, does anyone has any suggestions on how I could approach this differently?

bryanmac
  • 38,941
  • 11
  • 91
  • 99
TurqMage
  • 3,321
  • 2
  • 31
  • 52

2 Answers2

13

Another option is GCD. You can invoke a block on the main queue which gets run serially when the run loop runs. blocks aren't limited to one object like performSelectorOnMainThread.

dispatch_async(dispatch_get_main_queue(), ^{
   // code here
});

I wrote a more comprehensive comparison of performSelectorXXX and GCD here complete with samples:

GCD, Threads, Program Flow and UI Updating

Also, here's another related SO post:

GCD to perform task in main thread

Community
  • 1
  • 1
bryanmac
  • 38,941
  • 11
  • 91
  • 99
4

If you need to pass only one parameter, you should set up "withObject:" argument in method performSelectorOnMainThread:withObject:waitUntilDone. So your method should be declared as

-(void)setImageForButton:(id)parameter

and you should invoke method on main thread with:

[obj performSelectorOnMainThread:@selector(setImageForButton:) withObject:newArt waitUntilDone:YES];

Note ':' in @selector(setImageForButton:) this means that this method will be messaged with one argument, passed in withObject:

Johnnywho
  • 5,541
  • 2
  • 27
  • 20