NSOperationQueue似乎在几秒钟内完成

时间:2010-06-30 18:18:27

标签: iphone objective-c ios4 nsoperationqueue

我有一个自定义视图控制器,它实现了来自UITableViewDataSourceUITableViewDelegate协议。当我为我的表加载数据时(在我的viewDidLoad方法中),我创建了一个NSOperationQueue和一个NSInvocationOperation并将其添加到队列中。我抛出了一个活动指示器,viewDidLoad退出。

用于操作的方法结束活动指示器动画。

我注意到当操作完成时,在操作真正完成之前有一个5-7秒的暂停,即使NSLog看起来像是返回了操作的方法。

我曾尝试使用Instruments来确定暂停发生的位置,但我无法分辨,因为我的大部分CPU时间都花在了系统库中。

修改 这是一个缩写版本:

@implementation MyViewController
@synthesize ...

- (void)viewDidLoad {
    [super viewDidLoad];
    self.opsQueue = [[NSOperationQueue alloc] init];

    NSInvocationOperation *aiStartOp = [[[NSInvocationOperation alloc]
                                           initWithTarget:self
                                                 selector:@selector(showActivityIndicators)
                                                   object:nil] autorelease];
    [self.opsQueue addOperation:aiStartOp];

    NSInvocationOperation *dataOp = [[[[NSInvicationOperation alloc] 
                                         initWithTarget:self
                                               selector:@selector(dataUpdate)
                                                 object:nil] autorelease];
    [dataOp addDependency aiStartOp];
    [self.opsQueue addOperation:dataOp];

    NSInvicationOperation *aiStopOp = [[[NSInvicationOperation alloc]
                                          initWithTarget:self
                                                selector:@selector(hideActivityIndicators)
                                                  object:nil] autorelease];
    [aiStopOp addDependency:dataOp];
    [self.opsQueue addOperation:aiStopOp];
}

/* other stuff */

@end

为了清楚起见,队列中的最后一个操作是:

- (void)hideActivityIndicators {
    DLog(@"hiding activity indicator");
    self.portraitChartProgressView.hidden = YES;
    [self.portraitChartProgressIndicator stopAnimating];

    self.landscapeProgressView.hidden = NO;
    [self.landscapeProgressIndicator startAnimating];
}

我在日志中看到的是上面日志消息的输出,然后是5秒的暂停,最后是视图,其中隐藏了指示符。

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

需要在主线程上执行所有UI事件,绘图等。 您可以使用以下内容将呼叫转发到主线程。

- (void)hideActivityIndicators {

    if (![NSThread isMainThread]) 
         [self performSelectorOnMainThread:@selector(hideActivityIndicators) withObject:nil waitUntilDone:NO];

    DLog(@"hiding activity indicator");
    self.portraitChartProgressView.hidden = YES;
    [self.portraitChartProgressIndicator stopAnimating];

    self.landscapeProgressView.hidden = NO;
    [self.landscapeProgressIndicator startAnimating];
}

修改“

现在我更仔细一点,你可能不需要做的一件事就是通过添加NSOperationQueue来启动和停止“加载”视图。可能您需要在队列中做的唯一事情是数据更新,然后发布通知和委派以在数据操作完成时更新您的视图。

TopSongs示例项目非常好地展示了这一点。主线程的转发语句基于示例中AppDelegate.m文件中的代码。