arraysswiftpersistencenskeyedarchivernskeyedunarchiver

Archiving and unarchiving Arrays in the DocumentDirectory in Swift


I am trying to save a simple array of objects in the persistent memory by executing the following code:

let fileManager=NSFileManager()
     let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)

     if urls.count>0{

         let localDocumentsDirectory=urls[0]
         let archivePath=localDocumentsDirectory.URLByAppendingPathExtension("meditations.archive")
         NSKeyedArchiver.archiveRootObject(self.meditationsArray, toFile: archivePath.path!)
         let restored=NSKeyedUnarchiver.unarchiveObjectWithFile(archivePath.path!)

         print("restored \(restored)")
     }
}

Yet, when I print the restored date as in the code I find nil.
Conversely, if I use the CachesDirectory the array is soon after restored fine,
but when I reopen the app and try to load the data, it is lost. What is correct way to persistently save data?


Solution

  • I think the problem is that your are using URLByAppendingPathExtension, when you should be using URLByAppendingPathComponent. The "path extension" is the file extension, so your archivePath is "~/Documents.meditations.archive". It might be temporarily working with the CachesDirectory, because it's putting the data into a temporary file somewhere, or maybe just reading it back from memory. This should fix it:

    let fileManager = NSFileManager()
    let documentDirectoryUrls = fileManager.URLsForDirectory(.DocumentDirectory, .UserDomainMask)
    
    if let documentDirectoryUrl = documentDirectoryUrls.first {
        let fileUrl = documentDirectoryUrl.URLByAppendingPathComponent("meditations.archive")
    
        // Also, take advantage of archiveRootObject's return value to check if
        // the file was saved successfully, and safely unwrap the `path` property
        // of the URL. That will help you catch any errors.
        if let path = fileUrl.path {
            let success = NSKeyedArchiver.archiveRootObject(meditationArray, toFile: path)
    
            if !success {
                print("Unable to save array to \(path)")
            }
        } else {
            print("Invalid path")
        }
    } else {
        print("Unable to find DocumentDirectory for the specified domain mask.")
    }