【问题标题】:How to get Current Location with SwiftUI?如何使用 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?

标签: swift xcode swiftui cllocation


【解决方案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 中使用,还有一个名为 locationWillChangePassthroughSubject&lt;CLLocation, Never&gt; 可以通过 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)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
  • 2021-02-01
  • 2020-01-01
  • 2023-03-18
  • 2016-03-06
相关资源
最近更新 更多