// // HomeLocationProvider.swift // suixinkan // import CoreLocation /// 首页位置采集结果。 struct HomeLocationSnapshot: Sendable { let latitude: Double let longitude: Double let address: String } /// 首页位置采集,基于 CoreLocation 并提供可选逆地理。 final class HomeLocationProvider: NSObject, CLLocationManagerDelegate { private let manager = CLLocationManager() private var coordinateContinuation: CheckedContinuation? override init() { super.init() manager.delegate = self manager.desiredAccuracy = kCLLocationAccuracyBest } /// 请求当前位置与地址。 func requestSnapshot() async throws -> HomeLocationSnapshot { let status = manager.authorizationStatus if status == .notDetermined { manager.requestWhenInUseAuthorization() try await Task.sleep(nanoseconds: 300_000_000) } let resolvedStatus = manager.authorizationStatus guard resolvedStatus == .authorizedWhenInUse || resolvedStatus == .authorizedAlways else { throw HomeLocationProviderError.permissionDenied } let coordinate = try await requestCoordinate() let address = await reverseGeocode(latitude: coordinate.latitude, longitude: coordinate.longitude) return HomeLocationSnapshot( latitude: coordinate.latitude, longitude: coordinate.longitude, address: address ) } private func requestCoordinate() async throws -> CLLocationCoordinate2D { try await withCheckedThrowingContinuation { continuation in self.coordinateContinuation = continuation manager.requestLocation() } } private func reverseGeocode(latitude: Double, longitude: Double) async -> String { let location = CLLocation(latitude: latitude, longitude: longitude) let geocoder = CLGeocoder() do { let placemarks = try await geocoder.reverseGeocodeLocation(location) return placemarks.first?.formattedAddress ?? "" } catch { return "" } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.last else { return } coordinateContinuation?.resume(returning: location.coordinate) coordinateContinuation = nil } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { coordinateContinuation?.resume(throwing: error) coordinateContinuation = nil } } /// 首页定位错误。 enum HomeLocationProviderError: LocalizedError { case permissionDenied var errorDescription: String? { switch self { case .permissionDenied: "需要位置权限才能上线" } } } private extension CLPlacemark { var formattedAddress: String { [subLocality, locality, administrativeArea] .compactMap { $0?.trimmingCharacters(in: .whitespacesAndNewlines) } .filter { !$0.isEmpty } .joined(separator: "") } }