2008-10-03 39 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版本之间微妙地变化。

我最好的建议是不要使用后台线程中的东西,除非文档说它是安全的。