在 Swift 中的 DocumentDirectory 中归档和取消归档数组
Posted
技术标签:
【中文标题】在 Swift 中的 DocumentDirectory 中归档和取消归档数组【英文标题】:Archiving and unarchiving Arrays in the DocumentDirectory in Swift 【发布时间】:2016-04-16 17:05:17 【问题描述】:我试图通过执行以下代码在持久内存中保存一个简单的对象数组:
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 数组很快就会恢复正常, 但是当我重新打开应用程序并尝试加载数据时,它会丢失。持久保存数据的正确方法是什么?
【问题讨论】:
【参考方案1】:我认为问题在于您使用的是URLByAppendingPathExtension
,而您应该使用URLByAppendingPathComponent
。 “路径扩展名”是文件扩展名,因此您的 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.")
【讨论】:
【参考方案2】:我遇到了同样的问题,我无法使用 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)
【讨论】:
以上是关于在 Swift 中的 DocumentDirectory 中归档和取消归档数组的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 项目中使用 Objective C 类中的 Swift 类
Swift新手教程系列5-函数+selector在swift中的使用方法
从 Swift 3 中的 API 获取 AVPlayer 中的视频