我有一些代码通过UIView
创建的队列创建并添加了[[NSOperationQueue alloc] init]
子视图,这导致了奇怪的滞后行为。仅在异常长时间延迟后才添加子视图。
但后来我转而使用[NSOperationQueue mainQueue]
这些部分,响应能力正常。
我只想解释一下我用第一种方法看到的滞后行为。
答案 0 :(得分:2)
来自Apple doc
主题和您的用户界面
如果您的应用程序具有图形用户界面,建议您收到 用户相关事件并从您的帐户启动界面更新 应用程序的主要线程。 此方法有助于避免同步 与处理用户事件和绘图窗口相关的问题 内容。一些框架,如Cocoa,通常需要这样做 行为,但即使是那些不这样做的行为,保持这种行为 主线程具有简化管理逻辑的优点 你的用户界面。它有一些值得注意的例外 有利于从其他线程执行图形操作。对于 例如,QuickTime API包含许多可以执行的操作 从辅助线程执行,包括打开电影文件, 渲染电影文件,压缩电影文件,导入和 导出图像。同样,在Carbon和Cocoa中你可以使用二级 线程来创建和处理图像并执行其他与图像相关的操作 计算。使用辅助线程可以进行这些操作 提高性能。 如果您不确定特定的图形 虽然操作,计划从主线程
此外,根据thread programming guide,UI类不是线程安全的。
因此,请避免从与主线程不同的线程更新UI。
如果您运行NSOperation
(在队列中),您可以更新您的UI(例如,在下载了应用程序生命周期所需的一些数据之后)在主线程中执行方法,如下所示:
-(void)main {
// e.g the delegate could be the controller that has the view that you want to update
if (delegate) {
NSURL *url = [delegate urlForDownloadOperation:self];
if ( nil == url ) return;
self.downloadedImage = [[NSImage alloc] initWithContentsOfURL:url];
// e.g. rather than invoking processImage directly on the delegate, ensure that the method draw the image on the main thread
[delegate performSelectorOnMainThread:@selector(processImage:)
withObject:self waitUntilDone:YES];
}
}
或者您可以向需要更新UI的组件发送通知,如:
- (void)main {
NSURL *url = [delegate urlForDownloadOperation:self];
if ( nil == url ) return;
self.downloadedImage = [[NSImage alloc] initWithContentsOfURL:url];
// e.g. send a notificatio to inform some components that it is ready to update the UI with some content
[[NSNotificationCenter defaultCenter] postNotificationName:@"importData" object:self];
}
需要更新UI的组件将注册该通知,如
- (void)processImage:(NSNotification*)notification
{
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(processImage:) withObject:notification waitUntilDone:YES];
return;
}
// update the UI here, you are running on the main thread
}