From b7cc732dbcda3513526c779b9d83769a9ee5e1cc Mon Sep 17 00:00:00 2001 From: Gary Tokman Date: Mon, 3 May 2021 18:40:59 -0400 Subject: [PATCH] feat: add new extensions for CoreLocation --- .../CoreLocation/CLLocation.swift | 36 +++++++++++++++++++ .../CoreLocation/CLLocationCoordinate2D.swift | 35 ++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 Sources/ExtensionKit/CoreLocation/CLLocation.swift create mode 100644 Sources/ExtensionKit/CoreLocation/CLLocationCoordinate2D.swift diff --git a/Sources/ExtensionKit/CoreLocation/CLLocation.swift b/Sources/ExtensionKit/CoreLocation/CLLocation.swift new file mode 100644 index 0000000..03bc3de --- /dev/null +++ b/Sources/ExtensionKit/CoreLocation/CLLocation.swift @@ -0,0 +1,36 @@ +import CoreLocation +import Combine + +public extension CLLocation { + + /// `CLLocation` from `CLLocationCoordinate2D` + /// - Parameter coordinate: `CLLocationCoordinate2D` + convenience init(from coordinate: CLLocationCoordinate2D) { + self.init(latitude: coordinate.latitude, longitude: coordinate.longitude) + } + + /// Geocode location `Error` + enum GeocodeError: Error { + case invalid(String) + case empty(String) + } + + /// Reverse geocode a `CLLocation` + /// - Parameter location: `CLLocation` + /// - Returns: Future with Result<[`CLPlacemark`], `GeocodeError`> + func reverseGeocode(location: CLLocation) -> Deferred> { + Deferred { + Future { promise in + CLGeocoder().reverseGeocodeLocation(location) { placemarks, error -> Void in + if let err = error { + return promise(.failure(.invalid("\(String(describing: err))"))) + } + guard let marks = placemarks, !marks.isEmpty else { + return promise(.failure(.empty("\(String(describing: placemarks))"))) + } + return promise(.success(marks)) + } + } + } + } +} diff --git a/Sources/ExtensionKit/CoreLocation/CLLocationCoordinate2D.swift b/Sources/ExtensionKit/CoreLocation/CLLocationCoordinate2D.swift new file mode 100644 index 0000000..b6ff172 --- /dev/null +++ b/Sources/ExtensionKit/CoreLocation/CLLocationCoordinate2D.swift @@ -0,0 +1,35 @@ +import CoreLocation + +extension CLLocationCoordinate2D: Equatable { + + /// Equatable coordinates + public static func == (lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool { + lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude + } + +} + +extension CLLocationCoordinate2D: Codable { + + /// `CLLocationCoordinate2D` at (latitude: 0, longitude 0) + public static let zero = CLLocationCoordinate2D(latitude: 0, longitude: 0) + + /// Encode a `CLLocationCoordinate2D` + /// - Parameter encoder: Encoder + /// - Throws: `EncodingError` + public func encode(to encoder: Encoder) throws { + var container = encoder.unkeyedContainer() + try container.encode(longitude) + try container.encode(latitude) + } + + /// Decode `CLLocationCoordinate2D` from data + /// - Parameter decoder: Decoder + /// - Throws: `DecodingError` + public init(from decoder: Decoder) throws { + var container = try decoder.unkeyedContainer() + let longitude = try container.decode(CLLocationDegrees.self) + let latitude = try container.decode(CLLocationDegrees.self) + self.init(latitude: latitude, longitude: longitude) + } +}