集成高德 SDK 并替换所有定位相关的 CoreLocation 与 MapKit

This commit is contained in:
2026-07-07 11:49:22 +08:00
parent 3acbf6315b
commit 8a4a30111c
29 changed files with 748 additions and 240 deletions

View File

@ -0,0 +1,100 @@
//
// LocationProvider.swift
// suixinkan
//
import CoreLocation
import Foundation
/// `AMapLocationManager` Android `LocationProvider`
final class LocationProvider: NSObject, LocationProviding {
static let shared = LocationProvider()
private let permissionManager = CLLocationManager()
private let geocoder: LocationGeocoder
init(geocoder: LocationGeocoder = .shared) {
self.geocoder = geocoder
super.init()
permissionManager.desiredAccuracy = kCLLocationAccuracyBest
}
func requestSnapshot() async throws -> HomeLocationSnapshot {
try AMapBootstrap.requireConfigured()
try await ensureLocationPermission()
let manager = makeLocationManager()
return try await withCheckedThrowingContinuation { continuation in
let started = manager.requestLocation(withReGeocode: true) { location, regeocode, error in
if let error {
continuation.resume(throwing: error)
return
}
guard let location else {
continuation.resume(throwing: LocationProviderError.locationFailed)
return
}
let address = regeocode?.formattedAddress ?? ""
continuation.resume(returning: HomeLocationSnapshot(
latitude: location.coordinate.latitude,
longitude: location.coordinate.longitude,
address: address
))
}
if !started {
continuation.resume(throwing: LocationProviderError.locationFailed)
}
}
}
func requestCoordinate() async throws -> CLLocationCoordinate2D {
try AMapBootstrap.requireConfigured()
try await ensureLocationPermission()
let manager = makeLocationManager()
return try await withCheckedThrowingContinuation { continuation in
let started = manager.requestLocation(withReGeocode: false) { location, _, error in
if let error {
continuation.resume(throwing: error)
return
}
guard let location else {
continuation.resume(throwing: LocationProviderError.locationFailed)
return
}
continuation.resume(returning: location.coordinate)
}
if !started {
continuation.resume(throwing: LocationProviderError.locationFailed)
}
}
}
func reverseGeocode(latitude: Double, longitude: Double) async -> String {
await geocoder.reverseGeocode(latitude: latitude, longitude: longitude)
}
///
func ensureLocationPermission() async throws {
let initialStatus = permissionManager.authorizationStatus
if initialStatus == .notDetermined {
permissionManager.requestWhenInUseAuthorization()
try await Task.sleep(nanoseconds: 500_000_000)
}
let status = permissionManager.authorizationStatus
guard status == .authorizedWhenInUse || status == .authorizedAlways else {
throw LocationProviderError.permissionDenied
}
}
private func makeLocationManager() -> AMapLocationManager {
let manager = AMapLocationManager()
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.locationTimeout = 30
manager.reGeocodeTimeout = 10
manager.locatingWithReGeocode = true
return manager
}
}