2

In my app, there is a background download session. There are a lot of different tasks in this session and I want to be able to resume the tasks if the user quits while it is currently downloading. I don't know what is the best way to achieve this, I'm sure someone more experimented knows how to do this!

I have tried to recreate the download session using the same identifier, but I get this error:

Error Domain=NSCocoaErrorDomain Code=4 "“CFNetworkDownload_T95Ew7.tmp” couldn’t be moved to “medias” because either the former doesn’t exist, or the folder containing the latter doesn’t exist." UserInfo={NSSourceFilePathErrorKey=/Users/[username]/Library/Developer/CoreSimulator/Devices/18FAD568-1671-4212-A2D9-CA6DDA8F9B8F/data/Containers/Data/Application/AA90AA34-3B3F-443D-AB17-6220EBE09C1F/Library/Caches/com.apple.nsurlsessiond/Downloads/com.albinmichel.avantpremiere.AVP/CFNetworkDownload_T95Ew7.tmp, NSUserStringVariant=(
    Move
), NSDestinationFilePath=/Users/[username]/Library/Developer/CoreSimulator/Devices/18FAD568-1671-4212-A2D9-CA6DDA8F9B8F/data/Containers/Data/Application/3E9C5227-27FF-4A12-A0F4-CF5BA1402B1A/Documents/medias/38041.jpg, NSFilePath=/Users/[username]/Library/Developer/CoreSimulator/Devices/18FAD568-1671-4212-A2D9-CA6DDA8F9B8F/data/Containers/Data/Application/AA90AA34-3B3F-443D-AB17-6220EBE09C1F/Library/Caches/com.apple.nsurlsessiond/Downloads/com.albinmichel.avantpremiere.AVP/CFNetworkDownload_T95Ew7.tmp, NSUnderlyingError=0x600002ccae20 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

After debugging I have seen that the problem comes from the temp files that are missing. It's weird because it seems to be downloading since it takes some time to process each task.

After some research I have found that when the user kills the app, all download tasks get cancelled, I'm not sure if that is true... If that is, should I have some kind of persistent variable that checks whether the user killed the app while downloading and create the task again when the user launches the app?

Or is it simply a bad practice and a totally normal thing that the downloads gets cancelled and I should wait for the user to click the download button again instead of relaunching it automatically?

0ranga
  • 21
  • 3
  • I can't recall any app on iOS or macOS that resumes a download after being restarted, some apps supports resuming a download that was for some reason halted but that is only if the app is still running, – Joakim Danielson Jul 10 '23 at 11:46
  • when user exist app then you have to manage and kill background downloading thread, once you relaunch app then resume downloading you can use these functions application did terminate, check these links https://stackoverflow.com/questions/40754202/how-to-detect-when-app-is-force-closed-in-background-swift, https://stackoverflow.com/questions/9447690/ios-detect-when-application-exits?rq=3 https://stackoverflow.com/questions/40754202/how-to-detect-when-app-is-force-closed-in-background-swift – Chandaboy Jul 10 '23 at 11:54
  • @Chandaboy Thank you, I think I will use `applicationWillTerminate(_:)` and save all the data I need to recreate the downloadSession when the app is relaunched. – 0ranga Jul 11 '23 at 13:52
  • Actually @Chandaboy, I have a problem where when I recreate the downloadSession with the same identifier, I still get the error I listed in my original post. Even if I cancel all the tasks and use `invalidateAndCancel()` on the session, when I recreate the downloadSession, each task seems to go through the delegate and call the function `func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)` which causes the error. Do you know if there is any way to solve this? – 0ranga Jul 11 '23 at 13:56

1 Answers1

0

Select the project and go to the project's general settings. Choose the "Signing & Capabilities" tab. Enable the "Background Modes" capability. In the "Background Modes" section, enable the "Background fetch" and/or "Remote notifications" options. These options can be used to enable your application to run in the background. After making the necessary settings, you need to update your code to configure your application to work in the background. To perform ongoing download tasks in the background, you can use the URLSession class. URLSession is an API used to manage asynchronous network requests.

Here's a simple example:

func startBackgroundDownload() {
let url = URL(string: "http://www.example.com/file.txt")!

let configuration = URLSessionConfiguration.background(withIdentifier: "com.example.backgroundDownload")
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)

let task = session.downloadTask(with: url)
task.resume()}

extension YourViewController: URLSessionDelegate, URLSessionDownloadDelegate {
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
    // Actions to be performed when the download is complete
}

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
    // Actions to be performed when the download completes with an error
}}
  • Thank you for taking the time to answer but I have already done that. My downloads work perfectly in background, it's just when the user terminates the app while it is downloading that I have a problem. – 0ranga Jul 11 '23 at 13:53
  • Oh sorry. I understand, unfortunately I have no idea about it, but I will research it and come back. – Kerem DEMİR Jul 11 '23 at 15:48