0

我正在一个 Action 中运行一个冗长的任务,我想显示我在哪里。为此,我创建了一个文本字段并使用 setStringValue 进行了尝试:

[textField setStingValue: [NSSting stringWithFormat:@"%ld",currentValue]]

该代码有效,但不幸的是,它不是在每次迭代后更新 NSTextField,而是在整个操作完成时更新。

我究竟做错了什么?

4

2 回答 2

2

这是因为具有 Cocoa 框架的应用程序使用事件循环来执行操作,并且事件以完全串行的方式发生。

事件基本上是框架设计者无法预测或发现以延迟方式运行的任何类型的操作。由于您无法预测何时会执行点击,因此需要将它们视为事件;并且出于效率原因(因为如果不需要,您不想多次重绘组件),重绘操作也是事件。

您的操作响应用户事件(例如,单击按钮是一个事件)而运行,因此会阻止队列中等待的所有其他事件,直到它完成。但是,组件会重新绘制以响应不同的框架触发事件,因此文本字段必须等到您的操作完成才能重新绘制自身。这就是为什么您无法从操作内部直观地更改文本字段的值的原因。

为了通知您的用户您的任务的进度,您需要在不同的线程上运行它。关于线程有很多话要说,所以你可能应该阅读一些关于它们的内容。我也确信有很多示例说明如何在后台线程中运行长操作并相应地为整个 Internet 上的 Cocoa 更新 UI。

于 2012-10-12T15:52:03.150 回答
1

当您单击一个 UI 组件并进入 Action 块时,代码将在主线程上运行,即绘制 UI 的同一线程。如果您在该块中运行长时间运行的操作,则在您完成之前它不会绘制,因为它正忙于做您正在做的任何事情 - 您已经劫持了绘制线程。

正如其他地方所说,您需要生成另一个线程,然后让新线程执行长时间运行的操作,并偶尔发送消息让主线程更新 UI。

下一步,请阅读有关NSThread的 Apple 文档,特别是:

+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument

请注意,线程是一个不平凡的领域,如果您不小心,请为一些奇怪的行为做好准备。

于 2012-10-13T01:37:05.737 回答