Ios 在Swift中使用包含数据的非归档对象时的不确定行为

Ios 在Swift中使用包含数据的非归档对象时的不确定行为,ios,swift,nskeyedarchiver,nskeyedunarchiver,Ios,Swift,Nskeyedarchiver,Nskeyedunarchiver,我在Swift中遇到以下代码问题。我从我的一个应用程序中提取了代码,并设置了一个游乐场来测试它的行为 下面这行有时成功,有时失败: if var selectedCards = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? [Account : Card] { 在操场上跑步之间没有任何变化 如果有人能帮助我,我将不胜感激。这快把我逼疯了 当线路在操场发生故障时,它会出现以下错误: 执行被中断,原因:EXC\u BAD\u指令 (代码=E

我在Swift中遇到以下代码问题。我从我的一个应用程序中提取了代码,并设置了一个游乐场来测试它的行为

下面这行有时成功,有时失败:

if var selectedCards = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? [Account : Card] {
在操场上跑步之间没有任何变化

如果有人能帮助我,我将不胜感激。这快把我逼疯了

当线路在操场发生故障时,它会出现以下错误:

执行被中断,原因:EXC\u BAD\u指令 (代码=EXC_I386_INVOP,子代码=0x0

当我的应用程序中的线路出现故障时,它会出现相同的错误,并在调试控制台中打印:

致命错误:在展开可选值时意外发现nil

操场

import Foundation
科目类别

class Account: NSObject, Comparable, NSCoding, NSCopying {

    var email: String = ""
    var locked: Bool = false

    override var hashValue: Int {
        return email.hash
    }

    required init(email: String) {
        super.init()
        self.email = email
        self.locked = false
    }

    required init?(coder decoder: NSCoder) {
        email = decoder.decodeObjectForKey("email") as! String
        locked = decoder.decodeBoolForKey("locked")
    }

    func encodeWithCoder(coder: NSCoder) {
        coder.encodeObject(email, forKey: "email")
        coder.encodeBool(locked, forKey: "locked")
    }

    func copyWithZone(zone: NSZone) -> AnyObject {
        let account = self.dynamicType.init(email: self.email)
        account.email = self.email
        account.locked = self.locked
        return account
    }

    override func isEqual(object: AnyObject?) -> Bool {
        guard let account = object as? Account else { return false }
        return account == self
    }
}

func ==(lhs: Account, rhs: Account) -> Bool {
    let emailEqual = lhs.email == rhs.email
    return emailEqual
}

func <(lhs: Account, rhs: Account) -> Bool {
    return lhs.email < rhs.email
}
class Card: NSObject, Comparable, NSCoding {

    var id: String = ""
    var name: String = ""

    override var hashValue: Int {
        return id.hash
    }

    init(id: String, name: String) {
        super.init()
        self.id = id
        self.name = name
    }

    required init?(coder decoder: NSCoder) {
        id = decoder.decodeObjectForKey("id") as! String
        name = decoder.decodeObjectForKey("name") as! String
    }

    func encodeWithCoder(coder: NSCoder) {
        coder.encodeObject(id, forKey: "id")
        coder.encodeObject(name, forKey: "name")
    }

    override func isEqual(object: AnyObject?) -> Bool {
        guard let card = object as? Card else { return false }
        return card == self
    }
}

func ==(lhs: Card, rhs: Card) -> Bool {
    let idEqual = lhs.id == rhs.id
    let nameEqual = lhs.name == rhs.name
    return idEqual && nameEqual
}

func <(lhs: Card, rhs: Card) -> Bool {
    if lhs.name == rhs.name {
        return lhs.id < rhs.id
    }
    return lhs.name < rhs.name
}

…as?[帐户:卡]
:查看这两个类所需的可故障初始化程序,例如,强制类型转换
电子邮件=…as!String
id=…as!String
。如果解码器(例如,对于密钥
“id”
),这些将不会失败并返回
nil
在强制强制转换(
as
)之前,产生
nil
,相反,它们会崩溃。尝试使用对象解码的安全展开(例如可选绑定)重新写入这些初始化器,如果解码失败(因此初始化失败而不是崩溃),则返回
nil
。怀疑我可能只需要添加@objc(账户)在账户类之前,以及@objc(卡)在Card类之前,使用未损坏的类名Hanks dfri。这绝对值得一做。但是,它应该是有效的,这并不能解释为什么当数据相同时它有时有效,有时无效。
NSKeyedArchiver
与此无关,因为我们可以将相同的问题归结为只是显式地尝试创建将
NSDictionary
作为
[帐户:卡]
,即
让map:NSDictionary=[帐户:卡]
(或只是
[帐户:“foo”]
)。这也会偶尔失败,出现致命错误“在打开可选值时意外发现零”。自然地,
NSDictionary
不能保存
nil
的键,但我无法解释为什么
account
在作为键/值输入
NSDictionary
时会不确定地产生
nil
。似乎相关。
let account = Account(email: "user@domain.com")
let card = Card(id: "1", name: "Card 1")

let map: [Account : Card] = [account : card]

let data = NSKeyedArchiver.archivedDataWithRootObject(map)

if var selectedCards = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? [Account : Card] {
    let selectedCard = Card(id: "2", name: "Card 2")
    selectedCards[account] = selectedCard

    print("Success")
}