代码之家  ›  专栏  ›  技术社区  ›  Airsource Ltd

NSThread和UIViewController交互

  •  5
  • Airsource Ltd  · 技术社区  · 17 年前

    如果我产生一个新线程,然后在其中我将一个新的控制器推到我的UINavigationController上,使用如下代码。。。

    (a) 不起作用

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

    然后我发现视图出现了,但没有响应用户输入。

    如果我像这样修改代码

    (b) 工作

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

    然后一切正常。

    关于原因有什么提示吗?

    4 回复  |  直到 17 年前
        1
  •  2
  •   Jason Coco superfell    17 年前

    在您的情况下,这实际上取决于[app changeView]中发生了什么,但它停止响应的原因很可能是您在新的辅助线程上没有运行循环调度事件(下面将对此进行详细介绍)。但是,一般来说,从辅助线程更新GUI是一个非常糟糕的主意。正如您已经发现的,所有这些事件都应该经过主线程。

    第二个示例有效而不是第一个示例有效的主要原因是UIApplication在主线程上为您设置并处理运行循环和事件调度程序。因此,当您调用performSelectorInMainThread时,选择器将被分派到主运行循环,该循环随后能够处理gui输入和其他事件。事件调度程序也由UIApplication在主线程上运行和管理。

    因此,基本上,不要在辅助线程上执行任何GUI管理活动。将它们分派到主线程。如果您需要在辅助线程上进行处理(如计时器或异步调用等),那么您必须在该线程上启动并管理自己的运行循环(请参阅 NSRunLoop 有关管理跑步循环的更多信息)。

        2
  •  2
  •   Airsource Ltd    17 年前

    刚在iPhone线程文档中找到这个

    如果您的应用程序具有图形 用户界面,建议 您将收到与用户相关的事件和 从您的计算机启动界面更新 应用程序主线程。这 事件和图形窗口内容。 一些框架,如Cocoa, 通常需要这种行为,但是 您的用户界面。

    我仍然不知道到底是什么会导致某些东西显示出来,但却无法接收用户输入,但我将来会遵循这一指导原则。

        3
  •  2
  •   Evan DiBiase    17 年前

    正如文档中所说,“如果您不确定某个特定的图形操作,请计划从主线程开始执行。”

    一个好的经验法则是,如果一个类没有显式地被证明是线程安全的,那么它可能不是。此外,未被记录为线程安全的代码在被多个线程使用时可能不会快速失效,但可能只是表现出未定义的行为,如您所见。

        4
  •  0
  •   Louis Gerbarg    17 年前

    UIKit或AppKit中几乎没有一个UI代码是线程安全的。它是如何失败的是无关紧要的,因为如果你担心它是如何失败的,你正在做的事情将导致各种奇怪的错误,这些错误将在不同的操作系统版本之间微妙地改变。

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