import Foundation #if os(iOS) import CoreLocation #endif final class LocationService: NSObject { typealias LocationResult = Result<(Double, Double), LocationError> #if os(iOS) enum LocationError: Error { case servicesDisabled case denied case unavailable } #else enum LocationError: Error { case denied case unavailable } #endif #if os(iOS) private let manager = CLLocationManager() private var completion: ((LocationResult) -> Void)? #endif override init() { super.init() #if os(iOS) manager.delegate = self manager.desiredAccuracy = kCLLocationAccuracyHundredMeters #endif } func requestLocation(_ completion: @escaping (LocationResult) -> Void) { #if os(iOS) guard CLLocationManager.locationServicesEnabled() else { completion(.failure(.servicesDisabled)) return } self.completion = completion manager.requestWhenInUseAuthorization() manager.requestLocation() #else let defaults = UserDefaults.standard if defaults.bool(forKey: "location_permission_denied") { completion(.failure(.denied)) return } guard let latRaw = defaults.string(forKey: "last_location_lat"), let lngRaw = defaults.string(forKey: "last_location_lng"), let lat = Double(latRaw), let lng = Double(lngRaw) else { completion(.failure(.unavailable)) return } completion(.success((lat, lng))) #endif } } #if os(iOS) extension LocationService: CLLocationManagerDelegate { func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { let status = manager.authorizationStatus if status == .denied || status == .restricted { completion?(.failure(.denied)) completion = nil } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.first else { return } completion?(.success((location.coordinate.latitude, location.coordinate.longitude))) completion = nil } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { completion?(.failure(.unavailable)) completion = nil } } #endif