在我的应用程序中(仅显示相关代码),我有一个带有属性的类Test
var location: CLLocation
我使用存档
public func encode(with aCoder: NSCoder) {
aCoder.encode(location, forKey: "location")
}
它是未存档的使用
required convenience public init?(coder aDecoder: NSCoder) {
let unarchivedLocation = aDecoder.decodeObject(forKey: "location") as! CLLocation
self.init(location: unarchivedLocation)
}
单元测试使用
func test_archiningUnarchiving() {
// given
let location = CLLocation.init(latitude: 0.0, longitude: 0.0)
let test = Test(location: location)
// when
let data = NSKeyedArchiver.archivedData(withRootObject: test)
let unarchivedTest = NSKeyedUnarchiver.unarchiveObject(with: data) as? Test
// then
XCTAssertEqual(unarchivedTest!.location, location, "location was not correctly unarchived")
}
该测试失败:
XCTAssertEqual failed: ("<+0.00000000,+0.00000000> +/- 0.00m (speed -1.00 mps / course -1.00) @ 1/19/18, 3:30:50 PM Central European Standard Time") is not equal to ("<+0.00000000,+0.00000000> +/- 0.00m (speed -1.00 mps / course -1.00) @ 1/19/18, 3:30:50 PM Central European Standard Time") - location was not correctly unarchived
日志两次显示原始位置和未归档位置的完全相同的数据。
知道反正有什么问题吗?
最佳答案
问题不是归档,而是平等测试。如果比较两个不同的CLLocation
实例,即使它们是相同的,它将始终返回false
。
最重要的是,任何未明确实现NSObject
的isEqual:
子类(例如CLLocation
的情况)都将遇到此行为。
Using Swift with Cocoa and Objective-C: Interacting with Objective-C APIs说:
Swift提供了==
和===
运算符的默认实现,并对从Equatable
类派生的对象采用NSObject
协议。 ==
运算符的默认实现调用isEqual:
方法。对于从Objective-C导入的类型,您不应覆盖等号或标识运算符。
而且,Concepts in Objective-C Programming: Introspection告诉我们:
NSObject
的默认isEqual:
实现仅检查指针是否相等。
就个人而言,我希望NSObject
子类不会自动继承isEqual:
,但事实就是如此。
最重要的是,除非您知道NSObject
子类已正确实现isEqual:
覆盖,否则请勿尝试对其进行相等性测试。如果需要,请编写自己的方法,例如isEqual(to location: CLLocation)
(但不是isEqual(_:)
)执行两个CLLocation
对象的成员比较。
关于ios - 显然,CLLocation对象无法精确地存档/未存档,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48343477/