显然,CLLocation对象无法精确归档/取消归档

时间:2018-01-19 14:38:22

标签: ios unit-testing cllocation nskeyedarchiver nskeyedunarchiver

在我的应用中(仅显示相关代码),我有一个带有属性

的班级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

日志显示原始位置和未归档位置的两倍完全相同的数据 知道什么可能出错了吗?

1 个答案:

答案 0 :(得分:2)

问题不在于存档,而在于平等测试。如果您比较两个不同的CLLocation个实例,即使它们相同,也会始终返回false

底线,任何未明确实现NSObject的{​​{1}}子类(例如isEqual:的情况)都会遇到此行为。

react-modal-563说:

  

Swift提供CLLocation==运算符的默认实现,并对从===类派生的对象采用Equatable协议。 NSObject运算符的默认实现调用==方法...不应覆盖从Objective-C导入的类型的相等或标识运算符。

并且,Using Swift with Cocoa and Objective-C: Interacting with Objective-C APIs告诉我们:

  

isEqual:的默认NSObject实现只是检查指针是否相等。

就个人而言,我希望isEqual:子类不会自动继承NSObject,但它就是它。

最重要的是,除非您知道它已正确实现isEqual:覆盖,否则不要尝试测试NSObject子类的相等性。如果您愿意,可以编写自己的方法,例如: isEqual:(但不是isEqual(to location: CLLocation))执行两个isEqual(_:)对象的成员比较。