2

So I have a custom struct with one property of type String and another of type CLLocationCoordinate2D. Apparently, String conforms to Hashable and if I can extend CLLocationCoordinate2D to conform to Hashable, my custom struct will also be Hashable. Here's my attempt at extending CLLocationCoordinate2D:

extension CLLocationCoordinate2D {
    static func == (lhs: Self, rhs: Self) -> Bool {
        return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(self.latitude) //wasn't entirely sure what to put for the combine parameter but I saw similar things online
    }
}
nickcoding
  • 305
  • 8
  • 35

2 Answers2

11

You need to declare Hashable explicitly:

extension CLLocationCoordinate2D: Hashable {
    public static func == (lhs: Self, rhs: Self) -> Bool {
        return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
    }
    
    public func hash(into hasher: inout Hasher) {
        hasher.combine(latitude)
        hasher.combine(longitude)
    }
}
OOPer
  • 47,149
  • 6
  • 107
  • 142
1

CoreLocation and MapKit haven't been properly Swiftified yet. I recommend reusing functionality for them.

extension CLLocationCoordinate2D: HashableSynthesizable { }
extension MKCoordinateRegion: HashableSynthesizable { }
extension MKCoordinateSpan: HashableSynthesizable { }
/// A type whose `Hashable` conformance could be auto-synthesized,
/// but either the API provider forgot, or more likely,
/// the API is written in Objective-C, and hasn't been modernized.
public protocol HashableSynthesizable: Hashable { }

public extension HashableSynthesizable {
  static func == (hashable0: Self, hashable1: Self) -> Bool {
    zip(hashable0.hashables, hashable1.hashables).allSatisfy(==)
  }

  func hash(into hasher: inout Hasher) {
    hashables.forEach { hasher.combine($0) }
  }
}

private extension HashableSynthesizable {
  var hashables: [AnyHashable] {
    Mirror(reflecting: self).children
      .compactMap { $0.value as? AnyHashable }
  }
}