在后台下载过程中,我的NSURLSessionDelegate方法没有被调用

我正在尝试使用NSURLSession来build立一个下载,它将在后台继续。 我有一个名为DownloadManager的单例类,它构buildNSURLSession并启动下载任务,如下所示:

 - (id)init { self = [super init]; if (self) { self.queue = [[NSOperationQueue alloc] init]; self.queue.maxConcurrentOperationCount = 1; // Initialize the background session. self.session = [self backgroundSession]; } return self; } - (NSURLSession *)backgroundSession { static NSURLSession *session = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.mycompany.myapp.BackgroundSession"]; session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:self.queue]; }); return session; } - (void)startDownload:(Download *)download { NSURL *remoteURL = ... NSURLSessionDownloadTask *task = [self.session downloadTaskWithURL:remoteURL]; [task resume]; } 

我已经实现了NSURLSessionDelegateNSURLSessionDownloadDelegate方法,包括URLSessionDidFinishEventsForBackgroundURLSession: 此外,我的应用程序委托实现application:handleEventsForBackgroundURLSession:completionHandler:

但是,当我开始下载后,通过按主页button将应用程序移动到后台时,所有下载委托方法停止触发和application:handleEventsForBackgroundURLSession:completionHandler:永远不会被调用。 下载继续,如果我等待足够长的时间,那么URLSession:downloadTask:didFinishDownloadingToURL:被称为我的应用程序回到前台的那一刻。 这意味着我不能在后台进行任何后期处理(例如保存到核心数据,开始新的下载等)。

我试图在需要的情况下向我的plist添加“后台获取”后台模式,并试图更改我的标识符,用于创buildNSURLSessionConfiguration后台configuration, 如此答案中的build议。 我是否设置了这个错误,或者我不应该能够在后台处理下载委托事件?

在单个下载在后台完成时,您将看不到下载委托事件,而只是在重新启动应用程序之后。 例如,当所有的下载成功完成(当handleEventsForBackgroundURLSession被调用时),或者当你手动重新启动应用程序。

至于为什么你没有看到handleEventsForBackgroundURLSession调用,我只能想到一些(不可否​​认)的可能性:

  1. 确保应用程序委托中handleEventsForBackgroundURLSession的签名是绝对正确的(大小写,拼写等)。 一个小错字不会产生任何警告,但会导致它不被调用。 所以它应该是:

     - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { // save the completionHandler here } 
  2. 你确定所有的背景下载都完成了吗? 如果其中一个挂起或由于某种原因失败,将阻止后台会话的完成被触发,并且因为委托方法只在一切完成时被调用,这意味着您的应用程序不会被激活。 我build议您仔细检查下载是否完成。

  3. 你检查过设备的控制台吗? (如果转到Xcode“Organizer”的“Devices”部分,可以看到这个。)有时候会有一些有趣的诊断错误消息,后台守护进程会为您logging。 如果你还没有,请检查一下。 那里有很多有趣的东西。

  4. 如果你手动杀死应用程序通过SpringBoard(双击物理主页button,按住应用程序图标,直到它的摇晃,点击红色的“X”),这将杀死后台下载任务,因此你不会收到通知,所有的下载完成。 确保你实现了URLSession:task:didCompleteWithError:所以你可以看到这个错误(和其他)。

    但是,如果以编程方式崩溃应用程序(如WWDC 2013video“基础networking新增function”中所述) ,或者如果系统终止,则后台下载将正确完成,并且应用程序委托方法会正确调用。

只是几个想法要考虑。