4

I track downloads using two arrays, to track my downloads and to know where to save them:

private var filesToDownload: NSMutableArray = []
private let startedDownloads: NSMutableArray = []

When a download finishes remove them from both arrays and move the downloaded file to a persistent location.

    //is called once the download is complete
internal func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {

    print("download task", downloadTask.originalRequest!)
    print("download tasks", self.startedDownloads)
    // find matching manifestObject through finished downloadTask and use it to generate path

    let indexDownloadTask = self.startedDownloads.indexOfObjectIdenticalTo(downloadTask.originalRequest!)
    let listItem = self.filesToDownload.objectAtIndex(indexDownloadTask)

    // move file
    FileSystem.Instance().moveToRoot(location, relativeTo: listItem["file"] as! String)

    // remove downloadTask and matching item in filesToDownload to enshure the indexes of both arrays still matches
    self.startedDownloads.removeObjectAtIndex(indexDownloadTask)
    self.filesToDownload.removeObjectAtIndex(indexDownloadTask)

    print("Remaining Downloads1: ", self.startedDownloads.count)
    print("Remaining Downloads2: ", self.filesToDownload.count)

    // finished all downloads
    if self.startedDownloads.count == 0 {
        self.working = false
        self.cb(result: 0)
        print("Crazy shit, we finished downloading all files")
    }
}

Now when run my app it starts automatically all downloads. If I let them finish everything is fine. But when I click on stop in Xcode in the middle of the downloads and run it again, it seems to continue with previous downloads and will throw out of bound since the previous download is not yet in the array of started downloads of course.

Why do the previous downloads continue?

When using the simulator and clicking stopping and running creates a new folder with device "udid" and a new app "udid" so is it like a fresh install? or continue? if continue shouldn't it use the same folder to continue with the same files?

When a dowload fires finish, I move them from the temp location to a persistent location, but since it has made a new folder for the new click on run, all trys to move will fail anyway. I'm really confused, this seems so senseless.

I start them with

internal func download(url: NSURL) -> Void {
    self.working = true
    let session = self.getSession()
    let task = session.downloadTaskWithURL(url)
    self.startedDownloads.addObject(task.originalRequest!)
    task.resume()
}

and use this config

private let sessionConfig: NSURLSessionConfiguration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.company.app.background")
Cœur
  • 37,241
  • 25
  • 195
  • 267
user2834172
  • 861
  • 1
  • 9
  • 17
  • Have you configured your session for background downloading? – Duncan C Dec 01 '16 at 22:12
  • @DuncanC Yes, I did. Do background loadings continue when the app continues? If it's a continuation why with different folder, then all my moves after downloading will fail, since it's a different path. – user2834172 Dec 01 '16 at 22:14
  • Yes, if you enable background downloading then the download continues even if your app is terminated. With a normal app not running in Xcode, the app gets re-launched in the background once the download is done. I'm not sure what happens if you run the app from Xcode and then terminate it in Xcode . – Duncan C Dec 01 '16 at 22:40
  • If you don't want the app to keep downloading after you terminate it then you should disable background downloading. I suggest reading up on background downloading in the Xcode docs on `URLSession` – Duncan C Dec 01 '16 at 22:41
  • @DuncanC Oh i thought background means when in background/pause not when terminating it. But then if i terminate it, i still should see new files appearing in the folder what's not the case. – user2834172 Dec 01 '16 at 22:54
  • @DuncanC So in this case it doesn't matter that it's a singleton class and only start downloading if `!working`, then would have to save the state of working persitently? Mhm i will try for a read :/ – user2834172 Dec 01 '16 at 22:57
  • Go read the docs. It explains it. – Duncan C Dec 01 '16 at 23:00
  • @DuncanC thanks, you can answer with the argument of running still on termination, i would accept it as answer! – user2834172 Dec 01 '16 at 23:01

2 Answers2

2

If you have your app set up for background downloading then the system continues the download even after the app is terminated. For an app that's launched from the springboard, the system will re-launch your app in the background once the download is completed.

The docs tell you that when you get launched you should recreate your download session object and set up a delegate and you'll get the download complete message.

If you don't want a download started in the last run to be delivered at app launch then you probably don't want background downloading.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
0

you should remove your completion Handler from your appDelegate every time the task finished:

func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {

        DispatchQueue.main.async{
            if let appDelegate = UIApplication.shared.delegate as? AppDelegate, let completionHandler = appDelegate.backgroundTaskCompletionHandler{
                appDelegate.backgroundTaskCompletionHandler = nil
                completionHandler()
            }
        }

}
Mr Zee
  • 87
  • 7