我尝试使用NSURLSession
设置下载,该下载将在后台继续。
我有一个名为DownloadManager
的单例类,它构建NSURLSession
并启动这样的下载任务:
- (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];
}
我已实施NSURLSessionDelegate
和NSURLSessionDownloadDelegate
方法,包括URLSessionDidFinishEventsForBackgroundURLSession:
。此外,我的应用程序委托实现了application:handleEventsForBackgroundURLSession:completionHandler:
。
但是,当我在开始下载后按下主页按钮将我的应用程序移动到后台时,所有下载委托方法都会停止触发,并且永远不会调用application:handleEventsForBackgroundURLSession:completionHandler:
。下载继续,如果我等待足够长时间完成,那么当我将我的应用程序带回前台时,会调用URLSession:downloadTask:didFinishDownloadingToURL:
。这意味着我无法在后台进行任何后期处理(例如保存到核心数据,开始新的下载等)。
我尝试添加'背景提取'如果需要,我的plist的后台模式,我尝试更改用于创建NSURLSessionConfiguration
后台配置的标识符,如this answer中所示。我在设置时遇到了错误,或者我不能在后台处理下载委托事件?
答案 0 :(得分:9)
当个人下载在后台完成时,您不会看到调用的下载委托事件,而是仅在重新启动应用程序后才会看到。例如,当所有下载成功完成时(调用handleEventsForBackgroundURLSession
时)或手动重启应用程序时。
至于为什么你没有看到handleEventsForBackgroundURLSession
被召唤,我只能想到一对(不可否认,不太可能)的可能性:
确保您的app委托中handleEventsForBackgroundURLSession
的签名绝对正确(大小写,拼写等)。一个小错字不会产生任何警告,但它会导致它不被调用。所以它应该是:
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
{
// save the completionHandler here
}
您确定后台下载的全部正在完成吗?如果其中一个由于某种原因挂起或失败,那将阻止触发后台会话的完成,并且因为只在完成所有操作时调用委托方法,这意味着您的应用程序将不会被激活。我建议仔细检查所有下载是否已完成。
您检查过设备的控制台吗? (如果您转到Xcode“Organizer”的“Devices”部分,您可以看到这一点。)有时会有一些有趣的诊断错误消息,后台守护程序会为您记录。如果你还没有检查出来。那里有很多有趣的东西。
如果您通过SpringBoard手动终止应用程序(双击物理主页按钮,按住应用程序图标直到其摇晃,点击红色“x”),这将终止后台下载任务,因此您赢了不通知所有下载都已完成。确保您实施URLSession:task:didCompleteWithError:
,以便您可以看到此错误(以及其他任何错误)。
但是,如果我按照WWDC 2013视频What’s New in Foundation Networking中所示以编程方式使应用程序崩溃,或者系统终止该应用程序,则后台下载正确完成,并且正确调用应用程序委托方法。
只需考虑一些想法。
答案 1 :(得分:1)
我遇到类似的问题,当应用程序在后台下载内容时,从未调用过AppDelegate中的application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void)
。
原来,我在sharedContainerIdentifier
中设置了URLSessionConfiguration
。
在我从URLSessionConfiguration
中删除了这一行之后,一切开始起作用。
sessionConfiguration.sharedContainerIdentifier = "my.shared.group"