使用背景中的NSURLSession逐个下载100个文件的列表

时间:2014-04-29 05:23:40

标签: ios objective-c background-process nsurlsession nsurlsessionconfiguration

我已使用NSURLSession实施了针对iOS 7+的下载管理器应用。下载管理器具有要按优先级顺序下载的排队文件列表。当应用程序处于后台并且委托调用被正确调用时,下载工作正常。但是,当应用程序进入后台时,即使下载完成,也需要花费太多时间

NSURLSession delegate:- **URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)downloadURL

被叫。有时代理人根本没有被调用,当我来到前台时,会调用下载任务委托。这种延迟的原因是什么?

1 个答案:

答案 0 :(得分:0)

我遇到了一个非常类似的问题,即后台任务会启动但后来似乎暂停了。然后,当应用程序返回到前台时,任务将完成。

我通过记录-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite

的输出验证了这种情况

我发现解决这个问题的方法是如何存储,处理和执行完成处理程序。

在我的情况下,流程以

开头
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{

[self.fmStore performBackgroundRefresh:^(UIBackgroundFetchResult result) {

    //Set application badge if new data is available
    if (result==UIBackgroundFetchResultNewData) [UIApplication sharedApplication].applicationIconBadgeNumber++;
    completionHandler(result);

}];
}

远程通知开始下载过程。

管理下载的方法返回一个取决于新数据可用性的值

-(void)performBackgroundRefresh:(void (^)(UIBackgroundFetchResult))completion{
   if(newData) completion(UIBackgroundFetchResultNewData);
    else completion(UIBackgroundFetchResultNoData);
}

此时它返回到存储完成处理程序的ApplicationDelegate

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{
//Store completion handler for background session
self.sessionCompletionHandler=completionHandler;
}

最后,执行这段代码,调用完成处理程序并创建适当的通知

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
[session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
    if (![downloadTasks count]) {


        FM_AppDelegate *appDelegate=(FM_AppDelegate *)[[UIApplication sharedApplication] delegate];
        if (appDelegate.sessionCompletionHandler) {
            void (^completionHandler)() = appDelegate.sessionCompletionHandler;
            appDelegate.sessionCompletionHandler = nil;
            completionHandler();
        }
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [[NSNotificationCenter defaultCenter] postNotificationName:@"ContentRefreshNotification" object:Nil];
        }];
    }
}];
} 

这种来回过程在我的情况下发生,因为NSURLSession存在于作为ApplicationDelegate属性的对象中。如果将NSURLSession实现为ApplicationDelegate本身的属性,则所有这些代码都将存在于同一文件中。

希望这会有所帮助,但如果您需要更多信息,请参阅这两个教程12,因为我的代码基于我在这些内容中所读到的内容。