集成高德 SDK 并替换所有定位相关的 CoreLocation 与 MapKit
This commit is contained in:
@ -1,98 +0,0 @@
|
||||
//
|
||||
// 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<CLLocationCoordinate2D, Error>?
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
|
||||
/// 逆地理编码,供地图标记使用。
|
||||
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 ""
|
||||
}
|
||||
}
|
||||
|
||||
private func requestCoordinate() async throws -> CLLocationCoordinate2D {
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
self.coordinateContinuation = continuation
|
||||
manager.requestLocation()
|
||||
}
|
||||
}
|
||||
|
||||
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: "")
|
||||
}
|
||||
}
|
||||
@ -30,7 +30,7 @@ final class HomeViewModel {
|
||||
let locationReportService: LocationReportService
|
||||
private let appStore: AppStore
|
||||
private let commonMenuStore: HomeCommonMenuStore
|
||||
private let locationProvider: HomeLocationProvider
|
||||
private let locationProvider: any LocationProviding
|
||||
|
||||
private var timeoutDialogTriggered = false
|
||||
private var dismissedLocationTimeoutDialog = false
|
||||
@ -39,7 +39,7 @@ final class HomeViewModel {
|
||||
appStore: AppStore = .shared,
|
||||
locationStateStore: HomeLocationStateStore = HomeLocationStateStore(),
|
||||
commonMenuStore: HomeCommonMenuStore = HomeCommonMenuStore(),
|
||||
locationProvider: HomeLocationProvider = HomeLocationProvider()
|
||||
locationProvider: any LocationProviding = LocationProvider.shared
|
||||
) {
|
||||
self.appStore = appStore
|
||||
self.locationStateStore = locationStateStore
|
||||
|
||||
@ -27,11 +27,11 @@ final class ScenicSelectionViewModel {
|
||||
var onNavigateApplyStatus: ((String) -> Void)?
|
||||
|
||||
private let appStore: AppStore
|
||||
private let locationProvider: HomeLocationProvider
|
||||
private let locationProvider: any LocationProviding
|
||||
private var currentLat: Double?
|
||||
private var currentLng: Double?
|
||||
|
||||
init(appStore: AppStore = .shared, locationProvider: HomeLocationProvider = HomeLocationProvider()) {
|
||||
init(appStore: AppStore = .shared, locationProvider: any LocationProviding = LocationProvider.shared) {
|
||||
self.appStore = appStore
|
||||
self.locationProvider = locationProvider
|
||||
}
|
||||
@ -63,7 +63,7 @@ final class ScenicSelectionViewModel {
|
||||
let address = snapshot.address.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
currentLocationText = address.isEmpty ? "最近的景区" : address
|
||||
loadFromLocal()
|
||||
} catch HomeLocationProviderError.permissionDenied {
|
||||
} catch LocationProviderError.permissionDenied {
|
||||
onShowMessage?("未授予定位权限,无法获取附近景区")
|
||||
} catch {
|
||||
onShowMessage?("定位失败: \(error.localizedDescription)")
|
||||
|
||||
Reference in New Issue
Block a user