1

我有一个同步过程,有时(甚至很少)需要 20 秒。我曾经在后台调用选择器。有一个进度指示器会在同步完成的通知上停止动画,并且下面的代码会立即更改:

[self performSelectorInBackground:@selector(updateFunction) withObject:nil];

但为了让进度继续下去,我决定使用后台任务:

    UIApplication *application = [UIApplication sharedApplication]; //Get the shared application instance

    __block UIBackgroundTaskIdentifier background_task; //Create a task object

    background_task = [application beginBackgroundTaskWithExpirationHandler: ^ {
        [application endBackgroundTask: background_task]; //Tell the system that we are done with the tasks
        background_task = UIBackgroundTaskInvalid; //Set the task to be invalid

        //System will be shutting down the app at any point in time now
    }];

    //Background tasks require you to use asyncrous tasks

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //Perform your tasks that your application requires

        NSLog(@"\n\nRunning in the background!\n\n");
        [self updateFunction];

        [application endBackgroundTask: background_task]; //End the task so the system knows that you are done with what you need to perform
        background_task = UIBackgroundTaskInvalid; //Invalidate the background_task
        NSLog(@"Finished in the background!");
    });

但是现在,当任务完成时,通知会被发送(并执行),但表格中的单元格直到(有时)很长一段时间才会更新。因此,在我看来,“需求显示”在来自后台任务左右时不会触发,并且仅在定期刷新间隔左右更新。

有没有办法使用后台任务更新表格单元格,或者我错过了什么?

编辑:通知监听器是:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(refreshBttn)
                                             name:@"finishedUpdate"
                                           object:nil]; 

代码是:

- (void) refreshBttn {
    NSLog(@"Refresh Buttun action");
    iDomsAppDelegate *delegate = (iDomsAppDelegate *)[[UIApplication sharedApplication] delegate];
    if([delegate updating]){
        [_updateBttn setHidden:TRUE];
        [_activityIndicator startAnimating];         
    } else {
        [_updateBttn setHidden:FALSE];
        [_activityIndicator stopAnimating];        
    }
    [self setNeedsDisplay];
    [self setNeedsLayout];
}
4

3 回答 3

2

为了更新 UI,您必须从后台线程调用主线程上的函数,如下所示:

[self performSelectorOnMainThread:@selector(updateFunction) withObject:nil waitUntilDone:NO];

如果您需要传递任何变量,您可以继续并将它们添加到-withObject

于 2012-08-06T15:55:12.893 回答
2

您可以确保从您想要的任何队列接收到通知...

[[NSNotificationCenter defaultCenter] addObserverForName:SomeNotification
                                                  object:sender
                                                   queue:operationQueue
                                              usingBlock:^(NSNotification *){
    // Your notification will be processed in this block, and it will be
    // received on the notification queue you specify, regardless of what
    // thread the sender was running when the notification was posted.
}];

如果要确保在主线程上收到它,可以使用

[NSOperationQueue mainQueue]
于 2012-08-06T17:57:50.097 回答
0

您需要在后台线程和前台线程之间拆分逻辑。您发送的通知应该从主线程发送,以便您的 UI 对象监听它可以安全地更新自己。所以,updateFunction分成两块。也许是这样的:

NSLog(@"\n\nRunning in the background!\n\n");
[self updateFunctionBackground];
dispatch_async(dispatch_get_main_queue(), ^{
    // send your notification here instead of in updateFunction
    [[NSNotificationCenter defaultCenter] post...];
});
于 2012-08-06T16:19:29.250 回答