在NSOperationQueue非主队列上创buildUI元素会导致奇怪的行为

我有一些代码,通过由[[NSOperationQueue alloc] init]创build的队列创build和添加UIView子视图,并导致奇怪的laggy行为。 只有在延误时间过长之后才会添加子视图。

但后来我转而使用[NSOperationQueue mainQueue]来处理这些部分,并且响应性正常。

我只想解释一下我看到的使用第一种方法的滞后行为。

从苹果文档

线程和您的用户界面

如果您的应用程序具有graphics用户界面,则build议您接收与用户相关的事件,并从应用程序的主线程启动界面更新。 这种方法有助于避免与处理用户事件和绘制窗口内容相关的同步问题。 一些框架,比如Cocoa,通常需要这种行为,但即使对于那些没有的行为,在主线程中保持这种行为也有简化pipe理用户界面的逻辑的优点。 有一些值得注意的例外是从其他线程执行graphics操作是有利的。 例如,QuickTime API包含许多可以从辅助线程执行的操作,包括打开电影文件,呈现电影文件,压缩电影文件以及导入和导出图像。 同样,在Carbon和Cocoa中,您可以使用辅助线程来创build和处理图像,并执行其他图像相关的计算。 使用辅助线程进行这些操作可以大大提高性能。 如果您不确定某个特定的graphics操作,请计划从您的主线程执行此操作

另外,根据线程编程指南 ,UI类不是线程安全的。

所以,避免从与主线程不同的线程更新UI。

如果你运行一个NSOperation (在一个队列中),你可以更新你的UI(例如,在下载了你的应用生命周期所需的一些数据之后)在主线程中执行一个方法,如下所示:

 -(void)main { // eg 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]; // eg 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]; // eg 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 }