1

我有一个实现 fromUITableViewDataSourceUITableViewDelegate协议的自定义视图控制器。当我为我的表加载数据时(在我的viewDidLoad方法中),我创建 aNSOperationQueue和 aNSInvocationOperation并将其添加到队列中。我抛出一个活动指示器,然后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 秒的暂停,最后是带有隐藏指示器的视图。

有任何想法吗?

4

1 回答 1

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 文件中的代码。

于 2010-06-30T19:29:05.087 回答