Swift 使用 CoreLocation 获取设备的经纬度

请求权限

需要在 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 CoreLocation

class 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
// locationManager.distanceFilter = 10 // 感觉没啥用
}

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 SwiftUI

struct 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 // 精确度10m以内
kCLLocationAccuracyHundredMeters // 精确度100m以内
kCLLocationAccuracyKilometer // 精确度1000m以内
kCLLocationAccuracyThreeKilometers // 精确度3000m以内

.distanceFilter

我们无法直接控制 loctionManager 更新的频率,但可使用 distanceFilter 属性(单位米)进行间接控制。

它指设备(水平或垂直)移动多少米后才将另一个更新发送给委托。定位要求的精度越高,distanceFilter 属性的值越小,应用程序的耗电量就越大。

但是目前看下来,好像没什么效果。

参考:

  1. Updating the User’s Location with Core Location and Swift Concurrency in SwiftUI
  2. Tutorial: Connecting Core Location to a SwiftUI App
  3. SwiftUI获取用户的位置信息 CLLocationManager,CLLocationManagerDelegate
  4. Swift - 使用CoreLocation实现定位(经纬度、海拔、速度、距离等)
  5. An example how to use onReceive with @published
  6. difference between desiredAccuracy and distanceFilter

Swift 使用 CoreLocation 获取设备的经纬度
https://wonderhoi.com/2024/11/21/Swift-使用-CoreLocation-获取设备的经纬度/
作者
wonderhoi
发布于
2024年11月21日
许可协议