您想要实现的目标可以使用背景NSURLSession 来完成。虽然 AFNetworking 是基于 NSURLSession 我不太确定它是否可以与后台会话一起使用而你的应用程序没有。但是你真的不需要这个,NSURLSession 很容易使用。
作为第一步,您需要为后台会话创建会话配置:
let config = URLSessionConfiguration.background(withIdentifier: "de.5sw.test")
config.isDiscretionary = true
config.waitsForConnectivity = true
isDiscretionary 属性允许系统决定何时执行数据传输。 waitsForConnectivity(自 iOS 11 起可用)在没有互联网连接时让系统等待,而不是立即失败。
使用该配置对象,您可以创建 URL 会话。重要的部分是指定一个委托,因为当应用终止时,基于闭包的回调会丢失。
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
要执行上传,您要求会话创建一个上传任务,然后恢复它。对于上传任务,您首先创建您的URLRequest,指定 URL 和所有需要的标头。您要上传的实际数据需要写入文件。如果您将其作为Data 或流对象提供,则在您的应用终止后将无法上传。
let task = session.uploadTask(with: request, fromFile: fileUrl)
task.resume()
要获得上传成功或失败的通知,您需要实现URLSessionDataDelegate 方法urlSession(_:task:didCompleteWithError:)。如果错误为nil,则传输成功。
最后缺少的部分是处理在您的应用未运行时发生的事件。为此,您在应用程序委托中实现方法application(_:handleEventsForBackgroundURLSession:completionHandler:)。当系统决定您需要处理一些后台传输事件时,它会在后台启动您的应用并调用此方法。
您需要首先存储完成处理程序,然后使用您之前使用的相同配置重新创建您的 URLSession。然后,这将它称为您需要照常处理的事件的委托。一旦完成事件,它就会调用委托方法urlSessionDidFinishEvents(forBackgroundURLSession:)。从那里您需要调用传递给您的应用委托的完成处理程序。
会话配置提供了更多选项:
-
timeoutIntervalForResource: 系统应该尝试多长时间执行您的上传。默认为 7 天。
-
sessionSendsLaunchEvents:如果false 将不会启动应用程序来处理事件。当用户手动打开应用程序时,它们将被处理。默认为true。
这是一个小示例项目,展示了所有内容如何组合在一起:https://github.com/5sw/BackgroundUploadDemo