在iOS上使用后台任务进行UI更新

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

[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]; } 

你需要分离背景和前景线程之间的逻辑。 您要发送的通知应该从主线程发送,这样您的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...]; }); 

为了让用户界面更新,你必须从后台线程调用主线程的函数,如下所示:

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

如果您需要传递任何variables,则可以继续将其添加到-withObject

您可以确保通过您想要的任何队列收到通知…

 [[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]