我有一个同步过程,有时(甚至很少)需要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];
}
答案 0 :(得分:2)
为了更新UI,您必须从后台线程调用主线程上的函数,如下所示:
[self performSelectorOnMainThread:@selector(updateFunction) withObject:nil waitUntilDone:NO];
如果您需要传递任何变量,可以继续添加-withObject
答案 1 :(得分: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]
答案 2 :(得分: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...];
});