尝试在内容视图中使用 SwiftUI 获取用户位置但显示为零

Trying to get user location using SwiftUI in the content view but showing nil

我是初学者,尝试从 LocationManager 获取经纬度并使用 SwiftUI 将其显示在 ContentView 中,但结果显示为零。但是控制台打印来自 LocationManager class 的数据。不显示内容视图中的纬度和经度。谁能帮忙? (Xcode 11)

这是 LocationManager class

import Foundation
import CoreLocation
import Combine

class LocationManager: NSObject,CLLocationManagerDelegate, ObservableObject {
private let manager: CLLocationManager
var willChange = PassthroughSubject<LocationManager, Never>()

var getLat: String = ""
var getLon: String = ""

var lastKnownLocation: CLLocation? {
    willSet {
        willChange.send(self)
    }
}

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    if status == .denied {
        print("denied")
    }
    else{
        print("athorized")
        manager.requestLocation()
    }
}

func start() {
    manager.requestWhenInUseAuthorization()
    manager.startUpdatingLocation()
}

init(manager: CLLocationManager = CLLocationManager()) {
    self.manager = manager
    super.init()
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    print(error.localizedDescription)
}

func startUpdating() {
    self.manager.delegate = self
    self.manager.requestWhenInUseAuthorization()
    self.manager.startUpdatingLocation()
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    //print(locations)
    lastKnownLocation = locations.last
    
    getLat = "\(locations.last!.coordinate.latitude)"
    getLon = "\(locations.last!.coordinate.longitude)"
    
    showLocation()
}

func showLocation() {
    print("from showLocation")
    print("Latitude: \(getLat)")
    print("Longitude: \(getLon)")
}

}

This is the console that shows the latitude and longitude from LocationManager class

这是内容视图

import SwiftUI
import CoreLocation

struct ContentView: View {
    @State var managerDelegate = LocationManager()
    @State var manager = CLLocationManager()
    @ObservedObject var location = LocationManager()

    var lat: String {
        return "\(location.lastKnownLocation?.coordinate.latitude ?? 0.0)"
    }

    var lon: String {
        return "\(location.lastKnownLocation?.coordinate.longitude ?? 0.0)"
    }

    init() {
        self.manager.delegate = self.managerDelegate
        do {
            try self.manager.requestAlwaysAuthorization()
        }
        catch {
            print(error.localizedDescription)
            self.manager.requestAlwaysAuthorization()
        }
    }

    var body: some View {
        VStack {
            Text("Hello, World")
            Text("Latitude: \(lat)")
            Text("Longitude: \(lon)")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

This is output of ContentView in the Simulator

好的,我抽时间 阅读 你的代码,我有一个解决方案给你。

首先,您需要将委托设置为您正在观察的变量,在 ContentView.init():

self.manager.delegate = self.location

紧接着,您需要调用在 LocationManager 中定义的 startUpdating() 函数:

self.location.startUpdating()

最后,您可能想要删除 will-change 实现并选择更简单的实现:

@Published var lastKnownLocation: CLLocation?

已发布的包装器将自动为您触发对象更改。


重构

现在,如果您愿意,还可以将 init 语句减少到一行:

init() {
    self.location.startUpdating()
}

这意味着您可以自由删除几个属性:

`@State var managerDelegate = LocationManager()`

`@State var manager = CLLocationManager()`

TLDR; 这是代码的简化版本:

内容查看

import SwiftUI

struct ContentView: View {
    @ObservedObject var location = LocationManager()

    var lat: String {
        return "\(location.lastKnownLocation?.coordinate.latitude ?? 0.0)"
    }

    var lon: String {
        return "\(location.lastKnownLocation?.coordinate.longitude ?? 0.0)"
    }

    init() {
        self.location.startUpdating()
    }

    var body: some View {
        VStack {
            Text("Location breakdown")
            Text("Latitude: \(lat)")
            Text("Longitude: \(lon)")
        }
        .padding()
        .padding()
        .background(Color.white)
        .cornerRadius(10)
        .shadow(radius: 10)
    }
}

位置管理员

import Foundation
import CoreLocation

class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {
    private let manager = CLLocationManager()
    @Published var lastKnownLocation: CLLocation?
    
    func startUpdating() {
        self.manager.delegate = self
        self.manager.requestWhenInUseAuthorization()
        self.manager.startUpdatingLocation()
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        lastKnownLocation = locations.last
        
    }
    
}