在 Swift 的 DocumentDirectory 中归档和取消归档数组

Archiving and unarchiving Arrays in the DocumentDirectory in Swift

我正在尝试通过执行以下代码在持久内存中保存一个简单的对象数组:

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)")
     }
}

然而,当我按照代码打印恢复日期时,我发现 nil。
相反,如果我使用 CachesDirectory,数组在恢复后很快就会恢复正常,
但是当我重新打开应用程序并尝试加载数据时,它丢失了。持久保存数据的正确方法是什么?

我认为问题在于您使用了 URLByAppendingPathExtension,而您应该使用 URLByAppendingPathComponent。 "path extension" 是文件扩展名,所以你的 archivePath 是“~/Documents.meditations.archive”。它可能暂时与 CachesDirectory 一起工作,因为它将数据放入某个临时文件中,或者可能只是从内存中读回。这应该可以解决它:

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.")
}

我遇到了同样的问题,我无法使用 NSKeyedArchiver 归档和取消归档对象数组,我认为问题在于我使用了以下方法:

NSKeyedArchiver.archiveRootObject(arrayOfItems, toFile: FileManager.getFileURL("My-File-Name")!)

我认为此方法用于归档对象,而不是对象数组。

无论如何,我找到了解决问题的方法,方法是将整个数组包装在一个对象中,请查看以下内容:

let myArrayItemsContainer = ArrayItemsContainer()
myArrayItemsContainer.allItems = arrayOfItems
NSKeyedArchiver.archiveRootObject(myArrayItemsContainer, toFile: FileManager.getFileURL("My-File-Name")!)

并且我使用以下代码取消归档我的对象:

NSKeyedUnarchiver.unarchiveObject(withFile: FileManager.getFileURL("My-File-Name")!) as? ArrayItemsContainer

我还使用此扩展程序来使用 FileManager.getFileURL

public extension FileManager {
     /// Returns the URL of the file given a name
     ///
     /// - Parameter fileName: The file name of the file + extension
     /// - Returns: The URL as String
     static func getFileURL(_ fileName: String) -> String? {
     let fileURL = FileManager().urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first
         return (fileURL?.appendingPathComponent(fileName).path)
     }
}