如果通过performSelectorInBackground控制UI,会发生什么情况?
我读了一些信息,UI界面只在MainThread上更新。
我需要asynchronous更新一些UIButton
的,所以我使用performSelectorInBackground
,它在模拟器和设备(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]; } } }
我担心一些不需要的function会发生,如果我保持我的代码。 任何人都可以解释我有关performSelectorInBackground
细节?
为什么不使用它来更新用户界面,为什么它可以与我的应用程序? 无论如何debugging问题将不胜感激!
performSelectorInBackground:
几乎从来没有你想要的,几乎任何东西(当然不是自创buildGCD以来)。 它创build了一个你无法控制的新线程。 该线程将运行,只要您调度它的方法。
通过“小控制”,我的意思是你不会得到一个NSThread
对象,所以很容易无意中调用这个方法很多次,并且fork了无数个线程。 我在几个程序中看到过这种情况。
在iOS中,您几乎不应该手动创build线程。 GCD和NSOperation
几乎处理了手动线程可以做的所有事情,但更好。 您通常需要线程池,因此您不会始终旋转并旋转线程。 GCD给你。 你想限制你创build多less个线程,所以你不要压倒处理器。 GCD给你。 您希望能够轻松地优先处理您的后台操作。 GCD也给你。
所有这一切说,我不明白为什么你要在后台线程上执行上述操作。 几乎所有的工作都是UI更新。 永远不要尝试在后台线程上修改UI。 这是不确定的行为,当它出错的时候,它是非常错误的。 它在less数情况下工作的事实毫无意义。 UIKit不是线程安全的。 你应该在主线程上调用toggleToUpperWhenSingleShift
。 我没有看到任何东西会阻止你,上下文切换到后台线程的开销真的不值得在这里(即使它是安全的,这是不是)。
苹果强烈build议在后台线程中进行UI更改。
你应该使用performSelectorOnMainThread
或发送消息到UI线程的调度队列,并从那里做你的UI修改。
dispatch_async(dispatch_get_main_queue(), ^{ // your code here });
强烈build议不要从后台线程(例如计时器,通讯等)更新UI控件等。 这可能是有时很难识别的崩溃的原因。 而是使用这些来强制代码在UI线程(它总是“主”线程)上执行。
为进一步阅读。