iOS Question

Download fails when on first use or app goes in background

Alamofire 3.5.0, Swift2.2

I'm downloading ZIP files with the Alamofire download method, I've noticed that when I'm starting download process and apps goes background than the download fails with following error:

----------------------
error Optional(Error Domain=NSCocoaErrorDomain Code=4
"“CFNetworkDownload_pZ56nc.tmp” couldn’t be moved to “courses”
because either the former doesn't exist, or the folder containing
the latter doesn't exist." UserInfo=
{NSSourceFilePathErrorKey=
/private/var/mobile/Containers/Data/Application/[UUID]/tmp/CFNetworkDownload_pZ56nc.tmp,
NSUserStringVariant=(
Move
),
NSDestinationFilePath=
/var/mobile/Containers/Data/Application/[UUID]/Library/courses/course_302.zip,
NSFilePath=
/private/var/mobile/Containers/Data/Application/[UUID]/tmp/CFNetworkDownload_pZ56nc.tmp,
NSUnderlyingError=0x13f52f990 {Error Domain=NSPOSIXErrorDomain
Code=2 "No such file or directory"}})
----------------------


this is the code to download a file:

//...
var userLibraryPath:String = {
return NSSearchPathForDirectoriesInDomains(.LibraryDirectory, .UserDomainMask, true)[0]
}()

//...
let _coursePath:NSURL = NSURL(string: "file://\(userLibraryPath)/)")!
//...
let zipURL = _coursePath.URLByAppendingPathComponent("course_\(courseId).zip")
//if file exists destroy it
if let zipPath = zipURL?.path where NSFileManager.defaultManager().fileExistsAtPath(zipPath) {
do {
try NSFileManager.defaultManager().removeItemAtPath(zipPath)
} catch let error as NSError {
print(error)
}
}
//
let downloadRequest = Alamofire.download(Router.download(courseId), destination: { (url:NSURL, urlResponse:NSHTTPURLResponse) -> NSURL in
//
return zipURL!
//
}).progress({ (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
//
let progress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)

dispatch_async(GlobalMainQueue, {
self.notifyDownloadProgress(courseId, progress: progress)
})

}).response(completionHandler: { (request:NSURLRequest?, response:NSHTTPURLResponse?, data:NSData?, error:NSError?) in
self.removeFromQueue(courseId)
print("response")
print("----------------------")
print("error \(error)")
print("----------------------")
//here I would try to extract it
})


UPDATE I've just tested on iPhone 5 fresh install of the app and it doesn't have to go to background (e.g. via home button) to fail, it fails on the very first load (and any subsequent) untill after the app is killed and reopened.

Why is the "/private" bit added to the path? What am I doing wrong here?

Answer

And indeed it was a "No such file or directory" error.

When I've added:

//
let downloadRequest = Alamofire.download(Router.download(courseId), destination: { (url:NSURL, urlResponse:NSHTTPURLResponse) -> NSURL in
    let course = zipURL!.URLByDeletingLastPathComponent!.path!
    let fm = NSFileManager.defaultManager()
    var isDir:ObjCBool = false
    if(fm.fileExistsAtPath(path, isDirectory: &isDir) == false){
       //doesnt exist
       do {
           try fm.createDirectoryAtPath(path, withIntermediateDirectories: true, attributes: nil)
       } catch let error as NSError {
           //
           print(error)
       }
    }

    return zipURL!
    //
 })