如何使用 SwiftUI 获取当前位置?
Posted
技术标签:
【中文标题】如何使用 SwiftUI 获取当前位置?【英文标题】:How to get Current Location with SwiftUI? 【发布时间】:2019-06-10 20:22:20 【问题描述】:尝试使用 swiftUI 获取当前位置。下面的代码,无法使用 didUpdateLocations 委托进行初始化。
class GetLocation : BindableObject
var didChange = PassthroughSubject<GetLocation,Never>()
var location : CLLocation
didSet
didChange.send(self)
init()
【问题讨论】:
为什么你不能在这个类中创建 CLLocationManager? 【参考方案1】:以下代码有效(未准备好生产)。实现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()
【讨论】:
对于遇到错误的任何人:使用未解析的标识符“PassthroughSubject”,请确保将“import Combine”添加到文件顶部。【参考方案2】:我在https://github.com/himbeles/LocationProvider 上编写了一个带有使用说明的单文件 swift 包。它为 CLLocationManager 及其委托提供了一个ObservableObject
-type 包装类。
有一个 @Published
属性 location
可以直接在 SwiftUI 中使用,还有一个名为 locationWillChange
的 PassthroughSubject<CLLocation, Never>
可以通过 Combine 订阅。两者都会在CLLocationManager
的每个didUpdateLocations
事件上更新。
它还处理位置访问先前被拒绝的情况:默认行为是向用户显示在应用设置中启用访问的请求以及前往该位置的链接。
在 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()
【讨论】:
这在 iOS 14 上对我不起作用,应用程序因此错误而崩溃 => '无效参数不满足:!stayUp || CLClientIsBackgroundable(internal->fClient) @Ahmadreza 好像后台权限有问题?您是否按照包装的README.md
中的说明将Location
添加到UIBackgroundModes
?我已经使用 Xcode 12 beta 6 设置了一个最小的工作 SwiftUI 示例,它在设备和模拟器中都按预期运行。见github.com/himbeles/LocationProviderExample
@lsrggr,不,我没有,一定是这样,谢谢,但我还是使用“Paul Hutson”方法进行定位。【参考方案3】:
从 Xcode 11 beta 4 开始,您需要将 didChange
更改为 willChange
:
var willChange = PassthroughSubject<LocationManager, Never>()
var lastKnownLocation: CLLocation?
willSet
willChange.send(self)
【讨论】:
另外,在 Xcode11.1 上,您需要将BindableObject
更改为 ObservableObject
-
我还需要在 lastKnownLocation
声明前面加上 @Published
(XCode 12.0)以上是关于如何使用 SwiftUI 获取当前位置?的主要内容,如果未能解决你的问题,请参考以下文章