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:]:无法识别的选择器发送到实例
答案 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?。