我想在此处关注此前发布的帖子:Best practice to send a lot of data in background on iOS4 device?
基本上,我有一个名为getRequest的方法,它从Web服务器获取信息。我需要从Web服务器获得大约50条数据。所以同时,我有50个委托调用connectionDidFinishLoading。目前我的getRequest看起来像:
-(void) getRequestWithURL:(NSString *) requestURL
{
static int getRequest = 0;
NSLog(@"getRequest: %i", getRequest);
getRequest++;
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier taskID;
taskID = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"Time remaining: %f", app.backgroundTimeRemaining);
NSLog(@"Background task not completed");
[app endBackgroundTask:taskID];
}];
NSURLRequest *req = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:requestURL]];
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:req delegate:self] ;
[self startRequestWithConnection:con];
[req release];
if (taskID == UIBackgroundTaskInvalid) {
NSLog(@"Failed to create background task identifier");
}
}
然后在我的connectionDidFinishLoading中:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// process data from server
// endBackgroundTask:someTaskID???
}
我知道你可以多次调用beginBackgroundTaskWithExpirationHandler,但我不知道我在getRequest方法中做了什么,因为我每个只有一个变量__block UIBackgroundTaskIdentifier taskID
调用方法的时间。而且我也不确定是否需要在每次调用getRequest时在connectionDidFinishLoading方法中调用endBackgroundTask,因为你应该使用endBackgroundTask:call来平衡beginBackgroundTaskWithExpirationHandler。如果是这样,我怎么做,因为我的getRequest当前没有该基础设施?我是否需要50个ivars才能使connectionDidFinishLoading方法看到对getRequest的50个初始调用?感谢。
答案 0 :(得分:5)
正如您所说,您需要通过beginBackgroundTaskWithExpirationHandler
来电平衡endBackgroundTask
来电。
我想到的一个解决方案是这样的:
创建一个新的实例变量
UIBackgroundTaskIdentifier backgroundTaskID;
你正在计算请求,所以你也可以在connectionDidFinishLoading中减少getRequest:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// process data from server
getRequest--;
if (getRequest == 0 && backgroundTaskID != UIBackgroundTaskInvalid)
{
[[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
backgroundTaskID = UIBackgroundTaskInvalid;
}
}
现在后台任务在最后一个请求完成后结束。要仅启动一个后台任务,请在应用程序进入后台时调用的方法中启动它。
您需要聆听UIApplicationDidEnterBackgroundNotification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidEnterBackground)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
并实施方法
- (void)applicationDidEnterBackground:(NSNotification *)notification
{
if (getRequest > 0) {
backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
backgroundTaskID = UIBackgroundTaskInvalid;
}];
}
}
现在,您只有一个正在运行的后台任务,当您的应用程序进入后台时,该任务会自动启动,并且当您的所有请求都已完成时,您的运行请求将会终止。
另一项改进是将您的网络请求添加到NSOperationQueue,以避免手动计数并限制并发请求的数量。
答案 1 :(得分:1)
无论接下来的代码如何,正在完成的工作都很简单。该工作未包含在后台任务中。后台任务只是一个id和一个状态,告诉iOS框架你是否完成了你的任务。这取决于