【发布时间】:2017-01-20 06:03:00
【问题描述】:
我有一个复杂的类,其中包含许多嵌套类到几个层次,这些类被序列化并存储在 CoreData 表中。问题是,由于无法反序列化升级到 Swift 3 类的实例,因此在尝试解码嵌套类的实例时失败。
为了说明问题,使用实现 NSCoding 的内部类创建一个类定义:
导入基础
class Foo : NSObject, NSCoding {
class Bar : NSObject, NSCoding {
var x : Int
init(x:Int) {
self.x = x
}
required init?(coder aDecoder: NSCoder) {
self.x = aDecoder.decodeInteger(forKey: "x")
}
func encode(with aCoder: NSCoder) {
aCoder.encode(x, forKey:"x")
}
}
var bar:Bar
init(x:Int) {
self.bar = Bar(x: x)
}
required init?(coder aDecoder: NSCoder) {
self.bar = aDecoder.decodeObject(forKey: "bar") as! Bar
}
func encode(with aCoder: NSCoder) {
aCoder.encode(bar, forKey:"bar")
}
}
然后构建单元测试:
import XCTest
@testable import SerializationDemo
class SerializationDemoTests: XCTestCase {
func fileURL() -> URL {
let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
return dir.appendingPathComponent("foo.dat")
}
func testSerialize() {
let foo = Foo(x:42)
let data = NSKeyedArchiver.archivedData(withRootObject: foo)
let url = fileURL()
do {
try data.write(to: url)
} catch {
XCTFail("\(error)")
}
}
func testDeserialise() {
let url = fileURL()
do {
let data = try Data(contentsOf: url)
let myfoo = NSKeyedUnarchiver.unarchiveObject(with: data) as! Foo
XCTAssertEqual(myfoo.bar.x, 42)
} catch {
XCTFail("\(error)")
}
}
}
现在通过选择测试用例本身在一个会话中运行两个测试。这将按预期正确序列化和反序列化对象。
现在尝试独立运行两个单元测试。先连载。反序列化。第二个测试失败了
失败:捕获“NSInvalidUnarchiveOperationException”,“*** -[NSKeyedUnarchiver decodeObjectForKey:]: 无法为键 (bar) 解码类 (_TtCC17SerializationDemo3Foo3Bar) 的对象;班级可能 在源代码或未链接的库中定义”
一种解决方案是重构代码,使所有内部类都成为顶级,这还需要重命名这些类以使它们在应用程序中全局唯一。我宁愿不必以这种方式返工代码
【问题讨论】: