在我的应用程序中(仅显示相关代码),我有一个带有属性的类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

最重要的是,任何未明确实现NSObjectisEqual:子类(例如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/

10-11 14:57