LE SANG
LE SANG

Reputation: 11005

What's happen if control UI by performSelectorInBackground?

I read some informations that UI interface only update on MainThread.

I need to asynchronous update some UIButtons, so I use performSelectorInBackground and it's work fine on simulator and Device (iPad4).

[self performSelectorInBackground:@selector(toggleToUpperWhenSingleShift) withObject:nil];

- (void)toggleToUpperWhenSingleShift{
    shiftStateIndicator = 1;
    for (UIView *aPad in self.subviews) {
        if ( [aPad isKindOfClass:[UIButton class]] ) {
            UIButton *aButPad = (UIButton *)aPad;
            NSMutableString *currentTitle = [NSMutableString stringWithString:[aButPad titleForState:UIControlStateNormal]];
            NSString *firstChar = [currentTitle substringToIndex:1];
            [currentTitle replaceCharactersInRange:NSMakeRange(0, 1) withString:[firstChar uppercaseString]];
            [aButPad setTitle:currentTitle forState:UIControlStateNormal];
            [aButPad setTitle:currentTitle forState:UIControlStateHighlighted];

            currentTitle = [NSMutableString stringWithString:[aButPad titleForState:UIControlStateSelected]];
            firstChar = [currentTitle substringToIndex:1];
            [currentTitle replaceCharactersInRange:NSMakeRange(0, 1) withString:[firstChar uppercaseString]];
            [aButPad setTitle:currentTitle forState:UIControlStateSelected];
        }
    }
}

I'm worried some unwanted functions will happen if I keep my code. Can anyone explain me detail about performSelectorInBackground?

Why not use it to update UI and why it's OK with my app? Anyway to debug problem will appreciate!

Upvotes: 1

Views: 976

Answers (3)

Rob Napier
Rob Napier

Reputation: 299355

performSelectorInBackground: is almost never what you want, for almost anything (and certainly not since the creation of GCD). It creates a new thread that you have little control over. That thread will run for as long as the method you dispatch to it.

By "little control" what I mean is that you don't get an NSThread object back, so it is very easy to accidentally call this method many times and fork an unbounded number of threads. I've seen this happen in several programs.

In iOS, you should almost never manually create a thread. GCD and NSOperation handle almost everything that manual threads could do, but better. You typically want thread pooling so you don't spin up and spin down threads all the time. GCD gives you that. You want to cap how many threads you create so you don't overwhelm the processor. GCD gives you that. You want to be able to prioritize your background actions easily. GCD gives you that, too.

All that said, I can't figure out why you're trying to do the above operation on a background thread. Almost all the work is UI updates. You must never, ever, try to modify the UI on a background thread. It is undefined behavior, and when it goes wrong, it goes very wrong. The fact that it's worked in a few cases means nothing. UIKit is not thread safe. You should just call toggleToUpperWhenSingleShift on the main thread. I don't see anything in that should block you, and the overhead of context switching to a background thread really isn't worth it here (even if it were safe, which it's not).

Upvotes: 7

bpolat
bpolat

Reputation: 3908

It is strongly recommended not to update UI controls etc from a background thread (e.g. a timer, comms etc). This can be the cause of crashes which are sometimes very hard to identify. Instead use these to force code to be executed on the UI thread (which is always the “main” thread).

Go to http://www.ios-developer.net/iphone-ipad-programmer/development/threads/updating-ui-controls-on-background-threads

for further reading.

Upvotes: 0

lostInTransit
lostInTransit

Reputation: 71007

Making UI changes in a background thread is highly advised against by Apple.

You should either use performSelectorOnMainThread or send a message to the UI thread's dispatch queue and do your UI modifications from there.

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

Upvotes: 3

Related Questions