如何使用 SwiftUI 获取当前位置?
How to get Current Location with SwiftUI?
正在尝试使用 swiftUI 获取当前位置。在代码下方,无法使用 didUpdateLocations 委托进行初始化。
class GetLocation : BindableObject {
var didChange = PassthroughSubject<GetLocation,Never>()
var location : CLLocation {
didSet {
didChange.send(self)
}
}
init() {}
}
下面的代码有效(尚未准备好生产)。实施 CLLocationManagerDelegate
工作正常,lastKnownLocation
会相应更新。
别忘了在 Info.plist
中设置 NSLocationWhenInUseUsageDescription
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
private let manager = CLLocationManager()
var lastKnownLocation: CLLocation?
func startUpdating() {
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations)
lastKnownLocation = locations.last
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
manager.startUpdatingLocation()
}
}
}
从 Xcode 11 beta 4 开始,您需要将 didChange
更改为 willChange
:
var willChange = PassthroughSubject<LocationManager, Never>()
var lastKnownLocation: CLLocation? {
willSet {
willChange.send(self)
}
}
我在 https://github.com/himbeles/LocationProvider 上写了一个包含使用说明的单文件 swift 包。它为 CLLocationManager 及其委托提供了一个 ObservableObject
类型的包装器 class。
有一个可以直接在SwiftUI中使用的@Published
属性 location
,还有一个叫做locationWillChange
的PassthroughSubject<CLLocation, Never>
可以通过Combine订阅。两者都在 CLLocationManager
.
的每个 didUpdateLocations
事件上更新
它还处理位置访问先前被拒绝的情况:默认行为是向用户提出在应用程序设置中启用访问的请求,并link去那里。
在 SwiftUI(> iOS 14,> macOS 11)中,使用 as
import SwiftUI
import LocationProvider
struct ContentView: View {
@StateObject var locationProvider = LocationProvider()
var body: some View {
VStack{
Text("latitude \(locationProvider.location?.coordinate.latitude ?? 0)")
Text("longitude \(locationProvider.location?.coordinate.longitude ?? 0)")
}
.onAppear {
do {try locationProvider.start()}
catch {
print("No location access.")
locationProvider.requestAuthorization()
}
}
}
}
正在尝试使用 swiftUI 获取当前位置。在代码下方,无法使用 didUpdateLocations 委托进行初始化。
class GetLocation : BindableObject {
var didChange = PassthroughSubject<GetLocation,Never>()
var location : CLLocation {
didSet {
didChange.send(self)
}
}
init() {}
}
下面的代码有效(尚未准备好生产)。实施 CLLocationManagerDelegate
工作正常,lastKnownLocation
会相应更新。
别忘了在 Info.plist
NSLocationWhenInUseUsageDescription
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
private let manager = CLLocationManager()
var lastKnownLocation: CLLocation?
func startUpdating() {
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations)
lastKnownLocation = locations.last
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
manager.startUpdatingLocation()
}
}
}
从 Xcode 11 beta 4 开始,您需要将 didChange
更改为 willChange
:
var willChange = PassthroughSubject<LocationManager, Never>()
var lastKnownLocation: CLLocation? {
willSet {
willChange.send(self)
}
}
我在 https://github.com/himbeles/LocationProvider 上写了一个包含使用说明的单文件 swift 包。它为 CLLocationManager 及其委托提供了一个 ObservableObject
类型的包装器 class。
有一个可以直接在SwiftUI中使用的@Published
属性 location
,还有一个叫做locationWillChange
的PassthroughSubject<CLLocation, Never>
可以通过Combine订阅。两者都在 CLLocationManager
.
didUpdateLocations
事件上更新
它还处理位置访问先前被拒绝的情况:默认行为是向用户提出在应用程序设置中启用访问的请求,并link去那里。
在 SwiftUI(> iOS 14,> macOS 11)中,使用 as
import SwiftUI
import LocationProvider
struct ContentView: View {
@StateObject var locationProvider = LocationProvider()
var body: some View {
VStack{
Text("latitude \(locationProvider.location?.coordinate.latitude ?? 0)")
Text("longitude \(locationProvider.location?.coordinate.longitude ?? 0)")
}
.onAppear {
do {try locationProvider.start()}
catch {
print("No location access.")
locationProvider.requestAuthorization()
}
}
}
}