使用 NSUserDefaults 保存数组会使应用程序崩溃

Posted

技术标签:

【中文标题】使用 NSUserDefaults 保存数组会使应用程序崩溃【英文标题】:Saving array using NSUserDefaults crashes app 【发布时间】:2016-01-28 04:03:36 【问题描述】:

我觉得我做事正确,但在数据转换和检索结束时出现错误。请看下面的代码:

class Task:NSObject, NSCoding 
        var name:String
        var notes:String
        var date:NSDate
        var taskCompleted:Bool

        init(name:String, notes:String,date:NSDate, taskCompleted:Bool)
            self.name = name
            self.notes = notes
            self.date = date
            self.taskCompleted = taskCompleted
        

        required init(coder decoder: NSCoder)
            self.name = (decoder.decodeObjectForKey("name") as! String?)!
            self.notes = (decoder.decodeObjectForKey("notes") as! String?)!
            self.date = (decoder.decodeObjectForKey("date") as! NSDate?)!
            self.taskCompleted = (decoder.decodeObjectForKey("taskCompleted") as! Bool?)!
        

        func encodeWithCoder(coder: NSCoder) 
            coder.encodeObject(self.name, forKey: "name")
            coder.encodeObject(self.notes, forKey: "notes")
            coder.encodeObject(self.date, forKey: "date")
            coder.encodeObject(self.taskCompleted, forKey: "taskCompleted")
        
    

然后我保存并获取数据如下:

let nowData = NSKeyedArchiver.archivedDataWithRootObject([nowTasks])
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(nowData, forKey: "nowData")

let loadedData = defaults.dataForKey("nowData")
let loadedArray = NSKeyedUnarchiver.unarchiveObjectWithData(loadedData!) as! [Task]

当我调用 print(loadedArray.first) 时,我收到错误:NSArray 元素无法匹配 Swift Array 元素类型

【问题讨论】:

发布崩溃时打印到控制台的消息 而且你必须实现NSCoding 协议来归档一个带有NSKeyedArchiver 的类 上面添加了错误代码 您需要实现NSCoding 协议并使您的Task 成为NSObject 的子类 ***.com/questions/20627713/… 【参考方案1】:

看起来您的代码应该可以正常工作,即使您的解码器方法中正在进行一些非常奇怪的强制转换。试试这样:

class Task: NSObject, NSCoding 
    var name = String()
    var notes = String()
    var date: NSDate
    var taskCompleted: Bool
    init(name: String, notes: String, date: NSDate, taskCompleted: Bool)
        self.name = name
        self.notes = notes
        self.date = date
        self.taskCompleted = taskCompleted
    
    required init(coder decoder: NSCoder)
        self.name = decoder.decodeObjectForKey("name") as! String
        self.notes = decoder.decodeObjectForKey("notes") as! String
        self.date = decoder.decodeObjectForKey("date") as! NSDate
        self.taskCompleted = decoder.decodeBoolForKey("taskCompleted")
    
    func encodeWithCoder(coder: NSCoder) 
        coder.encodeObject(name, forKey: "name")
        coder.encodeObject(notes, forKey: "notes")
        coder.encodeObject(date, forKey: "date")
        coder.encodeBool(taskCompleted, forKey: "taskCompleted")
    

使用 plist 文件进行测试:

let task1 = Task(name: "task1", notes: "note a", date: NSDate(), taskCompleted: false)
let task2 = Task(name: "task2", notes: "note b", date: NSDate(), taskCompleted: true)

let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
let fileURL = documentsDirectory.URLByAppendingPathComponent("data.plist")

if let filePath = fileURL.path 
    NSKeyedArchiver.archiveRootObject([task1,task2], toFile: filePath)
    if let loadedArray = NSKeyedUnarchiver.unarchiveObjectWithFile(filePath) as? [Task] 
        print(loadedArray.count)

        print(loadedArray.first?.name ?? "")
        print(loadedArray.first?.notes ?? "")
        print(loadedArray.first!.date )
        print(loadedArray.first!.taskCompleted)

        print(loadedArray.last?.name ?? "")
        print(loadedArray.last?.notes ?? "")
        print(loadedArray.last!.date )
        print(loadedArray.last!.taskCompleted)
    

【讨论】:

在使用上述代码一段时间后,我设法让它工作。再次感谢! 还有一个问题。我可以使用同一个 .plist 文件来保存多个数组吗?我是否对相同的文件路径使用相同的NSKeyedArchiver.archiveRootObject(myArray, toFile: filePath) 检索它们? 你可以,但我认为为每个数组使用 plist 文件会更容易。您可以将 plist 文件保存在库目录的首选项文件夹中

以上是关于使用 NSUserDefaults 保存数组会使应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift 中保存和读取 NSUserdefaults 中的数组数组?

Swift:将一个对象数组和另一个对象数组保存到 NSUserDefaults 中

使用 Swift 将类中的结构保存到 NSUserDefaults

Swift - 将字典数组保存到 NSUserDefaults

使用 NSUserDefaults 保存 NSMutableArray 不起作用

NSUserDefaults NSMutable 数组未在会话之间保存