2013-04-01 72 views
1

我讀了一些UI界面只在MainThread上更新的信息。如果通過performSelectorInBackground控制UI會發生什麼?

我需要異步更新一些UIButton s,所以我使用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]; 
     } 
    } 
} 

我擔心一些不需要的功能會發生,如果我保持我的代碼。任何人都可以解釋我關於performSelectorInBackground的細節嗎?

爲什麼不使用它來更新用戶界面,爲什麼它可以用我的應用程序? 無論如何要調試問題將不勝感激!

+0

你是什麼意思*我需要異步更新一些UIButtons *?在UIView文檔的鏈接下面(閱讀**線程注意事項**)http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIView_Class/UIView/UIView.html –

+0

performSelectorInBackground與普通方法是異步的。我明白錯了嗎? –

+2

閱讀以下討論http:// stackoverflow。COM /問題/ 11122957/IS-IT-OK-來創建-A-的UIView-ON-A-後臺線程。 'performSelectorInBackground'是一種同步方法。這意味着其中的代碼將以串行方式執行。但在另一個線程。例如,異步模式是異步'NSURLConnection'使用的模式。 –

回答

7

performSelectorInBackground:幾乎從來沒有你想要的,幾乎任何東西(當然不是自創建GCD以來)。它創建了一個你無法控制的新線程。該線程只要調用它的方法就會運行。通過「小控制」我的意思是你沒有得到一個NSThread對象,所以很容易意外地多次調用這個方法,並分叉無限數量的線程。我在幾個程序中看到過這種情況。

在iOS中,您幾乎不應該手動創建線程。 GCD和NSOperation幾乎可以處理手動線程可以做的所有事情,但更好。您通常需要線程池,因此您不會隨時啓動並停止線程。 GCD給你。你想限制你創建多少個線程,所以你不會壓倒處理器。 GCD給你。您希望能夠輕鬆優先處理您的後臺操作。 GCD也給你。

所有這一切說,我不明白爲什麼你要在後臺線程上執行上述操作。幾乎所有的工作都是UI更新。永遠不要嘗試在後臺線程上修改UI。這是未定義的行爲,當它出錯時,它會變得非常錯誤。它在少數情況下起作用的事實並不意味着什麼。 UIKit不是線程安全的。您應該在主線程上撥打toggleToUpperWhenSingleShift。我沒有看到任何東西會阻止你,而且上下文切換到後臺線程的開銷在這裏確實是不值得的(即使它是安全的,哪些不是)。

+0

我需要說清楚!感謝您的詳細解答 –

3

由Apple強烈建議在後臺線程中進行UI更改。

您應該使用performSelectorOnMainThread或發送消息到UI線程的調度隊列,並從那裏做你的UI修改。

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

強烈建議不要從後臺線程(例如定時器,通訊科等)更新的UI控件等。這可能是有時很難識別的崩潰的原因。而是使用這些強制代碼在UI線程上執行(始終是「主」線程)。

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

進一步閱讀。

+1

請注意,定時器通常不會在後臺線程上運行。特別是'NSTimer'通常在主線程上運行,並且適用於UI更新。我不知道你是什麼意思的「通信」,但請注意,「NSURLConnection」回調通常也在主線程中。但你是正確的,你永遠不應該在後臺線程上更新UI控件。 –

相關問題