Как CLLocation реализует протокол Equatable?

Отвечая на другой вопрос о SO, я обнаружил, что класс CLLocation соответствует протоколу Equatable. Какой метод используется для определения равенства?

Точное совпадение широты и долготы? Точное совпадение широты/долготы и высоты? Точное совпадение широты, долготы, высоты и отметки времени? А скорость и курс? Как насчет CLLocation объектов, которые были созданы только с парой широта/долгота? Различные другие значения местоположения не являются необязательными, поэтому какой будет высота для местоположения, созданного с использованием init(latitude:longitude:)?


person Duncan C    schedule 13.09.2017    source источник
comment
Унаследовав от NSObject? Если вы попытаетесь вызвать == с двумя объектами CLLocation, вы увидите, что используется функция, объявленная для NSObject: public func ==(lhs: NSObject, rhs: NSObject) -> Bool. Правильный способ сравнить два экземпляра CLLocation, вероятно, состоит в том, чтобы использовать distance(from:) и сравнить его с порогом CLLocationDistance.   -  person JAL    schedule 14.09.2017
comment
Если вы хотите узнать, какие свойства используются для определения равенства, вам следует запустить несколько тестов с различными значениями и посмотреть, каковы результаты.   -  person rmaddy    schedule 14.09.2017


Ответы (3)


Просто полностью проверьте, что JAL сказал в своем ответе, я написал:

import Foundation
import UIKit
import CoreLocation

class ViewController: UIViewController{

    var cl1 = CLLocation()
    var cl2 = CLLocation()

    override func viewDidLoad() {
        super.viewDidLoad()
        if cl1 == cl2{

        }
    }
}

Затем я по команде нажал на == (из 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, который сравнивает только ссылки.

person Honey    schedule 17.09.2017
comment
вводящая в заблуждение реализация. == сопоставляется с ===. - person Duncan C; 22.03.2020

Как CLLocation реализует протокол Equatable?

Это не так. Нет переопределенной функции ==, которая сравнивает два экземпляра CLLocation. При вызове == с двумя экземплярами CLLocation используется функция NSObject ==:

public func ==(lhs: NSObject, rhs: NSObject) -> Bool

Чтобы фактически сравнить два экземпляра CLLocation, либо сравните свойства каждого из них (широта или долгота), либо используйте встроенный метод distance(from:) с двумя местоположениями и сравните его с порогом CLLocationDistance.

person JAL    schedule 14.09.2017
comment
Действительно, distance(from:) был бы полезным способом сравнения местоположений, где реализация == по умолчанию бесполезна. distance(from:isWithin:), позволяющее увидеть, находятся ли два местоположения на заданном расстоянии друг от друга (где isWithin выражается в метрах или километрах), было бы хорошим расширением. Однако distance(from:), вероятно, довольно дорогая функция. Я подозреваю, что внутри используется формула Хаверсина (которая позволяет вычислить расстояние по большому кругу между двумя точками на поверхности шира). - person Duncan C; 22.03.2020
comment
Формула Хаверсина включает довольно много триггера, который очень медленный. Для большинства приложений аппроксимация с помощью пифагорейского расстояния, скорее всего, подойдет и будет НАМНОГО быстрее. Вы могли бы даже создать версию, которая давала бы очень близкое приближение к формуле Хаверсина, используя расстояние Пифагора и грубое приближение кривой синусоиды, чтобы скорректировать результат в зависимости от расстояния от экватора. - person Duncan C; 22.03.2020
comment
Опять же, если ваши расчеты не критичны по времени, не беспокойтесь об этом. Просто используйте distance(from:) и покончим с этим. Вы не должны тратить время на оптимизацию кода, который на самом деле не является узким местом для вашего работающего приложения. (В конце концов, преждевременная оптимизация — корень всех зол.) - person Duncan C; 22.03.2020

Класс CLLocation, как и любой другой класс, соответствующий Equatable, реализует оператор (==)

И чтобы ответить на другие ваши вопросы, я решил запустить игровую площадку с этим кодом.

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

и единственный тип bool, который возвращает TRUE, это bool3.

поэтому независимо от того, одинаковы ли отдельные свойства разных объектов CLLocation, оператор == не будет рассматривать объекты как равные. Я предполагаю, что лучший способ для сравнения местоположений - это сравнить поля объектов CLLocation, которые вас интересуют.

person sfbarry14    schedule 13.09.2017
comment
Вы никогда не сравнивали loc3 с loc4! - person Duncan C; 14.09.2017
comment
взять его на спину. но спойлер это ложь - person sfbarry14; 14.09.2017
comment
Я провел быстрый тест в Objective-C, и оказалось, что CLLocation не переопределяет isEqual:. Два экземпляра CLLocation равны только в том случае, если они являются одним и тем же экземпляром. - person rmaddy; 14.09.2017
comment
Это довольно бесполезно. Похоже, что == на самом деле выполняет сравнение указателя (===), поскольку единственное сравнение, которое соответствует, — это сравнение местоположения с самим собой. - person Duncan C; 14.09.2017
comment
Класс CLLocation, как и любой другой класс, соответствующий Equatable, реализует оператор (==). Ну да, это аксиома. Я имел в виду, как он выполняет сравнение алгоритмически? - person Duncan C; 14.09.2017
comment
var loc7 = loc3.copy() as! CLLocation; var bool7 = loc7 == loc3 //Этот код дает false! - person Duncan C; 14.09.2017
comment
это как и ожидалось - person sfbarry14; 14.09.2017
comment
и скорее всего var loc8 = lov7; var bool8 = loc8 == lov7; правда - person sfbarry14; 14.09.2017
comment
Я чувствую возможность для расширения CLLocation, которое сравнивает только те свойства, которые вам нужны в вашем проекте. :) - person rmaddy; 14.09.2017
comment
Как я уже сказал в своем комментарии, это верно только из-за наследования от NSObject. Сам класс CLLocation не реализует ==. - person JAL; 14.09.2017
comment
Ваше утверждение CLLocation class much like any class that conforms to Equatable, implements the (==) operator неверно. - person JAL; 14.09.2017