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