I am trying to upload large files from iOS to a server using URLSessionConfiguration.background
object and uploadTask
function.
Things are looking good til now, but I wonder what actually happens behind the scene when the app goes into background state. I looked up the documents but it only roughly says "the session hands the transfers over to the system".
What I've done is just to initialize a singleton UploadManager
again in application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void)
after the tasks were done while in background. The manager instance creates a new URLSession
with the same identifier inside of it.
I thought I am just apparently creating "another" URLSession instance again, but how does it know about the previous tasks and their states to call the appropriate delegate methods? Does it receive the information back from process running by the system?
class UploadManager {
static let shared = UploadManager()
private var urlSession: URLSession!
private init() {
let sessionConfig = URLSessionConfiguration.background(withIdentifier: Bundle.main.bundleIdentifier! + ".upload")
sessionConfig.networkServiceType = .video
urlSession = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
}
...
}
extension UploadManager {
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
// do post-upload process for completed jobs
}
}
class AppDelegate: ... {
...
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
NSLog("š backgroundURLSession is done \(identifier)")
// just by instantiating, the appropriate completion delegate is called
let manager = VideoUploadManager.shared
}
}
You asked:
ā¦ how does it know about the previous tasks and their states to call the appropriate delegate methods?
It associates the background URLSession
tasks with the identifier string. So, assuming the app was not merely suspended, but needed to be relaunched from scratch, when it restarts, you create a background URLSession
with the particular identifier and now your delegate methods will be called. This all works because you use the same identifier string both when the tasks were first created as well as when the app is relaunched.
As Downloading Files in the Background: Recreate the Session If the App Was Terminated says:
If the system terminated the app while it was suspended, the system relaunches the app in the background. As part of your launch time setup, recreate the background session ā¦ using the same session identifier as before, to allow the system to reassociate the background download task with your session. You do this so your background session is ready to go whether the app was launched by the user or by the system. Once the app relaunches, the series of events is the same as if the app had been suspended and resumed, as discussed earlier in Handle App Suspension.
While that document focuses on background downloads, all of the general observations regarding background sessions are equally applicable to uploads.