在回答另一个关于SO的问题时,我发现CLLocation
类符合Equatable
协议。它使用什么方法来确定相等性?
是纬度/经度的精确匹配吗?纬度/经度和海拔的精确匹配?纬度、经度、海拔和时间戳的精确匹配?速度和航向呢?如果使用只有纬度/经度对的init(latitude:longitude:)
创建位置对象,那高度将是多少?该位置的其他各种值都不是可选项,因此我们应该如何处理?
在回答另一个关于SO的问题时,我发现CLLocation
类符合Equatable
协议。它使用什么方法来确定相等性?
是纬度/经度的精确匹配吗?纬度/经度和海拔的精确匹配?纬度、经度、海拔和时间戳的精确匹配?速度和航向呢?如果使用只有纬度/经度对的init(latitude:longitude:)
创建位置对象,那高度将是多少?该位置的其他各种值都不是可选项,因此我们应该如何处理?
CLLocation
如何实现Equatable协议?
它并没有。没有重写的==
函数来比较两个CLLocation
实例。当使用两个CLLocation
实例调用==
时,会使用NSObject
的==
函数:
public func ==(lhs: NSObject, rhs: NSObject) -> Bool
要比较两个CLLocation
实例,可以比较每个实例中你关心的属性(如纬度或经度),或者使用内置的distance(from:)
方法计算两个位置之间的距离,并将其与CLLocationDistance
阈值进行比较。
distance(from:)
是比较位置的有用方法,其中 ==
的默认实现是无用的。一个 distance(from:isWithin:)
可以让您查看两个位置是否在给定距离内(其中 isWithin
以米或千米表示),这将是一个很好的扩展。然而,distance(from:)
可能是一个相当昂贵的函数。我怀疑它在内部使用 Haversine 公式(它可以让您计算球面上两点之间的“大圆”距离)。 - Duncan Cdistance(from:)
函数即可完成。不要花费时间去优化那些实际上并不影响应用程序运行的代码。(毕竟,“过早优化是万恶之源”) - Duncan C为了完全验证JAL在他的回答中所说的,我写道:
import Foundation
import UIKit
import CoreLocation
class ViewController: UIViewController{
var cl1 = CLLocation()
var cl2 = CLLocation()
override func viewDidLoad() {
super.viewDidLoad()
if cl1 == cl2{
}
}
}
然后我按住 Command 键并点击 ==
(来自 if cl1 == cl2
)。它将带我到:
extension NSObject : CVarArg {
}
public func ==(lhs: Selector, rhs: Selector) -> Bool
public func ==(lhs: NSObject, rhs: NSObject) -> Bool
public struct NSZone {
}
为了仔细核对,我进行了命令点击 CLLocation
并看到:
open class CLLocation : NSObject, NSCopying, NSSecureCoding {
...
}
==
是因为它是从 NSObject
继承的,而 NSObject
只比较引用。==
映射到 ===
。 - Duncan CCLLocation类与任何符合Equatable协议的类一样,实现了(==)运算符
为了回答你的其他问题,我决定使用这段代码启动一个playground
import UIKit
import CoreLocation
var str = "Hello, playground"
var coordinate = CLLocationCoordinate2D.init(latitude: 42.0, longitude: 42.0)
var accuracy = CLLocationAccuracy.init(24.0)
var date = Date.init(timeIntervalSinceNow: 0)
var loc1 = CLLocation.init(coordinate: coordinate, altitude: 44.0, horizontalAccuracy: accuracy, verticalAccuracy: accuracy, timestamp: date)
var loc2 = CLLocation.init(coordinate: coordinate, altitude: 44.0, horizontalAccuracy: accuracy, verticalAccuracy: accuracy, timestamp: date)
var loc3 = CLLocation.init(latitude: 42.0, longitude: 42.0)
var loc4 = CLLocation.init(latitude: 42.0, longitude: 42.0)
var loc5 = CLLocation.init(coordinate: coordinate, altitude: 44.0, horizontalAccuracy: accuracy, verticalAccuracy: accuracy, course: .infinity, speed: 55.0, timestamp: date)
var loc6 = CLLocation.init(coordinate: coordinate, altitude: 44.0, horizontalAccuracy: accuracy, verticalAccuracy: accuracy, course: .infinity, speed: 55.0, timestamp: date)
var bool1 = loc1 == loc2 //false
var bool2 = loc2 == loc3 //false
var bool3 = loc2 == loc2 //true
var bool4 = loc1 == loc4 //false
var bool5 = loc5 == loc6 //false
唯一返回TRUE的bool是bool3。
因此,即使不同CLLocation对象上的各个属性相同,==运算符也不会将对象视为相等。我猜测比较位置的最佳方法是比较您感兴趣的CLLocation对象的字段。
NSObject
类?如果您尝试使用两个CLLocation
对象调用==
函数,则会发现使用的是为NSObject
声明的函数:public func ==(lhs: NSObject, rhs: NSObject) -> Bool
。比较两个CLLocation
实例的“正确”方法可能是使用distance(from:)
并将其与一个CLLocationDistance
阈值进行比较。 - JAL