请求权限 需要在 Targets 中的 Info 中添加:
Privacy - Location When In Use Usage Description
或者
Privacy - Location Always Usage Description
Privacy - Location Always and When In Use Usage Description
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 import CoreLocationclass LocationDataManager : NSObject , CLLocationManagerDelegate , ObservableObject { private var locationManager = CLLocationManager () @Published var currentPosition: CLLocationCoordinate2D ? @Published var currentSpeed: CLLocationSpeed ? @Published var authorizationStatus: CLAuthorizationStatus ? override init () { super .init () locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation } func locationManagerDidChangeAuthorization (_ manager : CLLocationManager ) { switch manager.authorizationStatus { case .authorizedWhenInUse: authorizationStatus = .authorizedWhenInUse manager.startUpdatingLocation() break case .restricted: authorizationStatus = .restricted manager.stopUpdatingLocation() break case .denied: authorizationStatus = .denied manager.stopUpdatingLocation() break case .notDetermined: authorizationStatus = .notDetermined manager.requestWhenInUseAuthorization() break default : break } } func locationManager (_ manager : CLLocationManager , didUpdateLocations locations : [CLLocation ]) { if let newPosition = manager.location { currentPosition = newPosition.coordinate currentSpeed = newPosition.speed } } func locationManager (_ manager : CLLocationManager , didFailWithError error : Error ) { print ("error: \(error.localizedDescription) " ) } func stopLocation () { locationManager.stopUpdatingLocation() } }
具体使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import SwiftUIstruct ContentView : View { @StateObject var locationDataManager = LocationDataManager () var body: some View { VStack { switch locationDataManager.authorizationStatus { case .authorizedWhenInUse: Text ("Your current location is:" ) Text (locationDataManager.currentPosition? .latitude.description ?? "Error" ) Text (locationDataManager.currentPosition? .longitude.description ?? "Error" ) case .restricted, .denied: Text ("前往 App 的设置中开启定位..." ) case .notDetermined: Text ("等待授权..." ) ProgressView () default : ProgressView () } } .onReceive(locationDataManager.$currentPosition ) { position in if locationDataManager.authorizationStatus == .authorizedWhenInUse { print ("Location Is Change" ) } } } } #Preview { ContentView () }
定位精度 有两个属性 .desiredAccuracy
与 .distanceFilter
。
.desiredAccuracy 1 2 3 4 5 6 kCLLocationAccuracyBestForNavigation kCLLocationAccuracyBest kCLLocationAccuracynearestTenMeters kCLLocationAccuracyHundredMeters kCLLocationAccuracyKilometer kCLLocationAccuracyThreeKilometers
.distanceFilter 我们无法直接控制 loctionManager 更新的频率,但可使用 distanceFilter 属性(单位米)进行间接控制。
它指设备(水平或垂直)移动多少米后才将另一个更新发送给委托。定位要求的精度越高,distanceFilter 属性的值越小,应用程序的耗电量就越大。
但是目前看下来,好像没什么效果。
参考:
Updating the User’s Location with Core Location and Swift Concurrency in SwiftUI
Tutorial: Connecting Core Location to a SwiftUI App
SwiftUI获取用户的位置信息 CLLocationManager,CLLocationManagerDelegate
Swift - 使用CoreLocation实现定位(经纬度、海拔、速度、距离等)
An example how to use onReceive with @published
difference between desiredAccuracy and distanceFilter