首页 > 解决方案 > 尝试在内容视图中使用 SwiftUI 获取用户位置但显示 nil

问题描述

我是一个初学者,试图从 LocationManager 获取纬度和经度,并使用 SwiftUI 在 ContentView 中显示它,但结果显示为零。但是控制台打印来自 LocationManager 类的数据。不显示内容视图中的纬度和经度。任何人都可以帮忙吗?(Xcode 11)

这是 LocationManager 类

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)")
}

}

这是显示 LocationManager 类的纬度和经度的控制台

这是内容视图

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()
    }
}

这是模拟器中 ContentView 的输出

标签: iosswiftuicore-locationlocationmanageruserlocation

解决方案


好吧,我发现自己有时间阅读您的代码,并且我为您提供了解决方案。

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

self.manager.delegate = self.location

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

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
        
    }
    
}

推荐阅读