如何在Swift 3中使用NSCoder编码[Character:Int]属性?

时间:2017-04-08 18:54:34

标签: ios swift3 nscoding

import UIKit

class Foo: NSObject, NSCoding {
    var cx: [Character : Int]

    init(cx: [Character : Int]) {
        self.cx = cx
    }

    // MARK: - <NSCoding>

    required convenience init(coder aDecoder: NSCoder) {
        let cx = aDecoder.decodeObject(forKey: "cxKey") as! [Character : Int]
        self.init(cx: cx)
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(cx, forKey: "cxKey")
    }
}

主叫:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        var foo = Foo(cx: ["C": 5, "X": 6])

        let encodedData = NSKeyedArchiver.archivedData(withRootObject: foo)
        print("encodedData: \(encodedData))")

        if let foo1 = NSKeyedUnarchiver.unarchiveObject(with: encodedData) as? Foo {
            print("cx = ", foo1.cx)
        } else{
            print("There is an issue")
        }
    }
}

Xcode抛出错误:***因未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:' - [_ SwiftValue encodeWithCoder:]:无法识别的选择器发送到实例

1 个答案:

答案 0 :(得分:2)

<强>原因

这是因为Character中的cx - 类型键将被装箱为_SwiftValue个对象,这些对象将被发送encodeWithCoder:,从而导致无法识别的选择器异常。

请参阅SwiftValue.h顶部的评论:

  

这实现了用于携带Swift的Objective-C类   已经桥接到Objective-C对象的值没有特殊   处理。该类对用户代码不透明,但是NSObject - 和   NSCopying - 符合并且被Swift运行时理解   动态转换回包含的类型。

<强>解决方案

如果您可以将cx的类型更改为[String : Int],则所有内容都可以开箱即用(无双关语)。

否则,您必须将cx中的Foo.encode(with:)转换为可编码的内容(例如[String : Int]),反之亦然。

有关代码,请参阅How do I encode Character using NSCoder in swift?How do I encode enum using NSCoder in swift?