我对beginBackgroundTaskWithExpirationHandler做了一些研究,我不认为我正确理解它。我的印象是,如果我们的应用程序进入后台,我可以在其中包含一个长任务,该任务继续运行。因此,当您第一次运行我们的应用程序时,您可以从我们的服务器下载更多数据,为用户提供更多信息。由于这可能需要一段时间,我希望此任务在后台和睡眠模式下运行(如果可能)。
我的原始函数没有在用户点击下载时调用的beginBackgroundTaskWithExpirationHandler,如下所示:
-(void) HandleDownload:(NSNotification *)notification
{
DataManager *dmgr = [TestApp sharedDelegate].AppDataManager;
NSString *nextPacketName = [dmgr GetNextPacketName];
int totalNumberPackets = [dmgr GetRowCountForTable:@"Manifest"];
if (nextPacketName == nil)
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:DownloadReferenceSequenceNotification object:nil];
self.ProgressLabel.hidden = YES;
self.ProgressBar.hidden = YES;
}
else
{
self.ProgressLabel.hidden = NO;
self.ProgressLabel.text = [NSString stringWithFormat:@"Downloading %@", nextPacketName];
self.ProgressBar.hidden = NO;
self.ProgressBar.progress += 1. / (totalNumberPackets);
WebServiceManager *wmgr = [WebServiceManager sharedInstance];
[wmgr GetPacket:nextPacketName]; // This function creates the NSURL and starts the request
}
}
假设应用程序位于前台,此函数可以正常工作。我尝试将此任务放在后台的是:
-(void) HandleDownload:(NSNotification *)notification
{
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier taskID;
taskID = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"Background task not completed");
[app endBackgroundTask:taskID];
DataManager *dmgr = [TestApp sharedDelegate].AppDataManager;
NSString *nextPacketName = [dmgr GetNextPacketName];
int totalNumberPackets = [dmgr GetRowCountForTable:@"Manifest"];
if (nextPacketName == nil)
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:DownloadReferenceSequenceNotification object:nil];
self.ProgressLabel.hidden = YES;
self.ProgressBar.hidden = YES;
}
else
{
self.ProgressLabel.hidden = NO;
self.ProgressLabel.text = [NSString stringWithFormat:@"Downloading %@", nextPacketName];
self.ProgressBar.hidden = NO;
self.ProgressBar.progress += 1. / (totalNumberPackets);
WebServiceManager *wmgr = [WebServiceManager sharedInstance];
[wmgr GetPacket:nextPacketName]; // This function creates the NSURL and starts the request
}
NSLog(@"Time remaining: %f", app.backgroundTimeRemaining);
}];
if (taskID == UIBackgroundTaskInvalid) {
NSLog(@"Failed to create background task identifier");
}
}
我是否正确地尝试将我长期运行的任务包装在beginBackgroundTaskWithExpirationHandler块中?它看起来并不像我,因为expiratinHandler块中的所有代码都不会被调用。提前谢谢!
答案 0 :(得分:1)
我只是在研究同样的功能才第一次使用它,但我看到你似乎缺少的是对endBackgroundTask的平衡调用: 您在到期处理程序的顶部有它,但只有在达到时间限制时才会调用它。它需要在您尝试完成的任务结束时添加。假设您的流程在到期之前完成,它就会被调用。
-(void) HandleDownload:(NSNotification *)notification
{
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier taskID;
taskID = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"Background task not completed");
[app endBackgroundTask:taskID];
DataManager *dmgr = [TestApp sharedDelegate].AppDataManager;
NSString *nextPacketName = [dmgr GetNextPacketName];
int totalNumberPackets = [dmgr GetRowCountForTable:@"Manifest"];
if (nextPacketName == nil)
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:DownloadReferenceSequenceNotification object:nil];
self.ProgressLabel.hidden = YES;
self.ProgressBar.hidden = YES;
}
else
{
self.ProgressLabel.hidden = NO;
self.ProgressLabel.text = [NSString stringWithFormat:@"Downloading %@", nextPacketName];
self.ProgressBar.hidden = NO;
self.ProgressBar.progress += 1. / (totalNumberPackets);
WebServiceManager *wmgr = [WebServiceManager sharedInstance];
[wmgr GetPacket:nextPacketName]; // This function creates the NSURL and starts the request
}
NSLog(@"Time remaining: %f", app.backgroundTimeRemaining);
[app endBackgroundTask:taskID];
}];