符合类到NSCoding

时间:2017-01-04 07:56:45

标签: ios swift plist nscoding file-writing

我将以下Person类符合NSCoding协议。

class Person: NSObject, NSCoding{

    var age:Int
    var height: Double
    var name: String

    init(age:Int, height: Double, name:String){
        self.age = age
        self.height = height
        self.name = name
    }

    func encode(with aCoder: NSCoder){
        aCoder.encode(age, forKey: "age")
        aCoder.encode(height, forKey: "height")
        aCoder.encode(name, forKey: "name")
    }

    required init?(coder aDecoder: NSCoder){
        age = aDecoder.decodeObject(forKey: "age") as! Int **//error**
        height = aDecoder.decodeObject(forKey: "height") as! Double
        name = aDecoder.decodeObject(forKey: "name") as! String
        super.init()
    }


}

然后,我创建了这个类的数组。我使用NSKeyedArchiver将它存档到一个plist,一切都很好。但是,当我试图取消归档时,我遇到了一个错误,涉及展开一个可选的nil。错误出现在标记为Person的类中。这是我使用的代码:

 if let people = unarchive(){
            print(people)
 }

这里是取消归档的功能:

func unarchive()->[Person]?{
    let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
    let documentDirectory = paths[0]
    let path = documentDirectory.appending("ObjectData.plist")
    let fileManager = FileManager.default
    if(!fileManager.fileExists(atPath: path)){
        if let bundlePath = Bundle.main.path(forResource: "ObjectData", ofType: "plist"){
            do{
                try fileManager.copyItem(atPath: bundlePath, toPath: path)
            }catch{
                print("problem copying")
            }
        }
    }
    if let objects = NSKeyedUnarchiver.unarchiveObject(withFile: path){
        if let people = objects as? [Person]{
            return people
        }else{
            return nil
        }
    }else{
        return nil
    }
}

2 个答案:

答案 0 :(得分:0)

IntDouble未归档为对象。对于aDecoder.decodeObject(forKey: <key>)nil将始终返回as!,将nilaDecoder.decodeInteger(forKey: "age") aDecoder.decodeDouble(forKey: "height") 一起使用会导致您的应用崩溃。

所以,改为使用:

name

对于{{1}}字段,您可以保留代码。

答案 1 :(得分:-1)

你应该对Int和Double使用正确的解码方法。您可以将以下代码粘贴到游乐场中并进行测试:

import Foundation

class Person: NSObject, NSCoding{

    var age:Int
    var height: Double
    var name: String

    init(age:Int, height: Double, name:String){
        self.age = age
        self.height = height
        self.name = name
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(age, forKey: "age")
        aCoder.encode(height, forKey: "height")
        aCoder.encode(name, forKey: "name")
    }

    required init?(coder aDecoder: NSCoder) {
        age = aDecoder.decodeInteger(forKey: "age")
        height = aDecoder.decodeDouble(forKey: "height")
        name = aDecoder.decodeObject(forKey: "name") as! String
        super.init()
    }
}

let john = Person(age: 30, height: 170, name: "John")
let mary = Person(age: 25, height: 140, name: "Mary")

let guys = [john, mary]

let data = NSKeyedArchiver.archivedData(withRootObject: guys)
let people = NSKeyedUnarchiver.unarchiveObject(with: data)

dump (people)