2008-10-03 42 views
5

如果我生成一個新的線程,然後在它我推一個新的控制器到我的UINavigationController,使用這樣的代碼......NSThread和UIViewController的互動

(一)不工作

-(void)myCallbackInThread 
{ 
    // move on... 
    UIApplication* app = [UIApplication sharedApplication]; 
    [app changeView]; 
} 

那麼我發現該視圖出現,但不響應用戶輸入。

如果我改變這樣

(二)工作

-(void)myCallbackInThread 
{ 
    // move on... 
    UIApplication* app = [UIApplication sharedApplication]; 
    [app performSelectorOnMainThread:@selector(moveToMain) withObject:nil waitUntilDone:FALSE]; 
} 

代碼然後一切都運行得很好。

任何提示爲什麼?

+0

您是否在控制檯窗口中獲取任何輸出內容? 我發現與iPhone上的線程,如果你正在做一些有趣的事情,它會輸出日誌消息。 – Lounges 2008-10-03 16:53:41

回答

2

在你的情況下,它確實取決於[app changeView]中發生了什麼,但是它停止響應的原因很可能是你的新輔助線程沒有運行循環調度事件。但是,一般來說,從輔助線程更新GUI是非常糟糕的主意。正如你已經發現的,所有這些事件都應該通過主線程。

您的第二個示例工作而不是第一個的主要原因是UIApplication在主線程上爲您設置和處理運行循環和事件分派器。所以,當你調用performSelectorInMainThread時,選擇器會被分派到主運行循環,然後它能夠​​處理你的gui輸入和其他事件。事件調度程序也由主線程上的UIApplication運行和管理。

所以基本上,不要在輔助線程上執行任何GUI管理活動。將這些分發給主線程。如果您需要在輔助線程上進行處理(例如定時器或異步電話等)。),那麼你必須在該線程上啓動並管理自己的運行循環(有關管理運行循環的更多信息,請參見NSRunLoop)。

2

剛剛發現這個在iPhone線程文檔

如果您的應用程序有一個圖形 用戶界面,建議 您收到用戶有關的事件和 開始從 應用程序的主線程界面更新。這種方法有助於避免與處理用戶事件和繪圖窗口內容相關的同步問題。一些框架,比如Cocoa, 通常需要這種行爲,但是 它也具有 的優勢,簡化了管理你的用戶界面的邏輯。

我仍然沒有看到實際上會導致顯示內容但不能接收用戶輸入的內容,但我將在未來遵循該準則。

2

正如文檔所述,「如果您不確定特定的圖形操作,請計劃從您的主線程執行此操作。」

一個好的經驗法則是,如果一個類沒有明確記錄爲線程安全的,那麼它可能不是。此外,沒有記錄爲線程安全的代碼在多線程使用時可能不會快速失敗,但可能會顯示未定義的行爲,如您所見。

0

幾乎沒有UIKit或AppKit中的UI代碼是線程安全的。它如何失敗是無稽之談,因爲如果你擔心如何失敗,你正在做的事情會導致各種奇怪的錯誤,無論如何將在不同的OS版本之間微妙地變化。

我最好的建議是不要使用後臺線程中的東西,除非文檔說它是安全的。