Best place to call `completionHandler` received in `handleEventsForBackgroundURLSession` in case of uploading?

445 views Asked by At

I am using URLSessionConfiguration.background for uploading and downloading content while my app is not foreground. The code that I'm using to create a background session is as below:

    private var session: URLSession!
    private override init() {
        super.init()

        let config = URLSessionConfiguration.background(withIdentifier: Constants.backgroundSessionIdentifer)
        config.sessionSendsLaunchEvents = true
        session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
    }

In application delegate, I receive a completion handler and store it as a property of UploadDownloadService which is a singleton.

    func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {

        Logger.debug(#function)
        UploadDownloadService.shared.backgroundCompletionHandler = completionHandler
    }

I'm executing the completion handler in urlSessionDidFinishEvents as apple demonstrated. My code is given below:

    func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {

        Logger.debug(#function)

        delegate?.urlSessionDidFinishEventsCalled()
        DispatchQueue.main.async {
            [weak self] in
            guard let backgroundCompletionHandler = self?.backgroundCompletionHandler else {
                return
            }

            Logger.debug("Executing background completion handler.")
            backgroundCompletionHandler()
            self?.backgroundCompletionHandler = nil
            self?.delegate?.didCallBackgroundCompletionHandler()
        }
    }

Now what I've found is urlSession(_ session:, downloadTask:, didFinishDownloadingTo location:) is called before urlSessionDidFinishEvents so I am sure that my downloaded file is saved to a permanent location before I call the completion handler inside urlSessionDidFinishEvents.

But I'm confused about the upload case. I didn't find any delegate method that is called before urlSessionDidFinishEvents method. The only delegate method I found for upload that is called when the app is awake is urlSession(_ session:, task:, didCompleteWithError:). Which is called after urlSessionDidFinishEvents.

Now in this scenario, I've two questions in mind.

1. From where should I call the completion handler so that I'm sure all of my post-processing is done after upload(In this case I want to query the database, update and send a message. I'm building a chat application)? Is it okay to delay the completion handler call while I do my processings and call it from outside of the urlSessionDidFinishEvents method?

2. How much time do I get approximately after I call the completion handler?

Note: I've done a lot of googling before posting, found a single related question here. But the only answer(as of now) on that post doesn't answer my question. So I've decided to ask the question elaborately(describing my scenario) here.

0

There are 0 answers