【问题标题】:Encoding and decoding custom subclass object getting fatal error: unexpectedly found nil while unwrapping an Optional value编码和解码自定义子类对象出现致命错误:在展开可选值时意外发现 nil
【发布时间】:2017-09-16 20:07:58
【问题描述】:

我有 2 个对象,1 个是另一个的子类。当我尝试取消归档子对象时,即使我手动测试归档和取消归档对象,我也会得到fatal error: unexpectedly found nil while unwrapping an Optional value

具体来说,我在以下位置崩溃:

let subobjectsArray = NSKeyedUnarchiver.unarchiveObject(with: subobjects) as? [Subobject] {

调用Subobject的解码初始化器

required init(coder aDecoder: NSCoder) {
            degree1 = aDecoder.decodeObject(forKey: degree1Key) as! CLLocationDegrees // get nil error here

这让我得出结论,我一定是对子对象进行了错误的编码和解码,但我不知道我在编码方面做错了什么。

如果有人能告诉我我做错了什么,将不胜感激!

代码

测试归档和取消归档的功能:

func unarchiveSubobjects() -> [Subobject] {
    //Manually encode a subobject
    let subobjects = [Subobject(name: "testing", degree1: CLLocationDegrees(45))]
    let data = NSKeyedArchiver.archivedData(withRootObject: subobjects)
    userDefaults.set(data, forKey: Key.UserDefaults.subobjects)
    
    // Decode object does not work and crashes with nil error
    if let subobjects = userDefaults.value(forKey: Key.UserDefaults.subobjects) as? Data,
        let subobjectsArray = NSKeyedUnarchiver.unarchiveObject(with: subobjects) as? [Subobject] { // crashes on the 2nd let statement
        return subobjectsArray
    }
    return [Subobject]()
}

Subobject.swift

class Subobject: Superobject {
    var degree1: CLLocationDegrees
    
    private let degree1Key = "degree1"
    
    init(name: String, degree1: CLLocationDegrees) {
        self.degree1 = degree1
        
        super.init(name: name)
    }
    
    // MARK: NSCoding
    
    required init(coder aDecoder: NSCoder) {
        degree1 = aDecoder.decodeObject(forKey: degree1Key) as! CLLocationDegrees // get nil error here
        
        super.init(coder: aDecoder)
    }
    
    public override func encode(with aCoder: NSCoder) {        
        aCoder.encode(self.degree1, forKey: degree1Key)
        
        super.encode(with: aCoder)
    }
}

Superobject.swift

class Superobject: NSObject, NSCoding {

    var name: String
    
    private let nameKey = "name"
    
    init(name: String){
        self.name = name
    }
    
    // MARK: NSCoding
    
    required init(coder aDecoder: NSCoder) {
        name = aDecoder.decodeObject(forKey: nameKey) as! String
    }
    
    public func encode(with aCoder: NSCoder) {
        aCoder.encode(self.name, forKey: nameKey)
    }
}

【问题讨论】:

    标签: swift nsuserdefaults nscoding nskeyedarchiver nskeyedunarchiver


    【解决方案1】:

    而不是解码一个对象解码实际类型Double

    degree1 = aDecoder.decodeDouble(forKey: degree1Key)!
    

    由于CLLocationDegreesDouble 的类型别名,它应该可以工作,或者您需要桥接转换该值。

    【讨论】:

    • 解码CLLocationDegrees有什么问题? B/c 我更喜欢解码CLLocationDegrees,因为subobject 的初始化方式是采用CLLocationDegrees 的度数输入
    • 对于 NSCoder 而言 CLLocationDegrees / Double 不是一个对象。由于代码在此行中崩溃,因此出现了问题。
    • 哇,你是绝对正确的。我不知道CLLocationDegreesDouble 的类型别名。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-29
    相关资源
    最近更新 更多