使用MVVM模式处理SwiftUI和CoreLocation

使用MVVM模式处理SwiftUI和CoreLocation,swift,xcode,mvvm,swiftui,core-location,Swift,Xcode,Mvvm,Swiftui,Core Location,我正在尝试使用MVVM模式实现SwiftUI和CoreLocation。我的LocationManager助手工作正常。但是如何更改我的LocationViewModel的属性呢?我在LocationViewModel中实现了LocationManager的@ObservedObject。这是我的问题 我没有一个想法来实现动态更改的属性。我的LocationView中没有任何更改。只要按下一个按钮,任何东西都能正常工作一次。但是LocationViewModel必须在每次更改LocationMa

我正在尝试使用MVVM模式实现SwiftUICoreLocation。我的
LocationManager
助手工作正常。但是如何更改我的
LocationViewModel
的属性呢?我在
LocationViewModel
中实现了
LocationManager
@ObservedObject
。这是我的问题

我没有一个想法来实现动态更改的属性。我的LocationView中没有任何更改。只要按下一个按钮,任何东西都能正常工作一次。但是
LocationViewModel
必须在每次更改
LocationManager
时更改这些属性

总之,我想显示当前用户的位置

// Location Manager as Helper

import Foundation
import CoreLocation

class LocationManager: NSObject, ObservableObject {

    let locationManager = CLLocationManager()
    let geoCoder = CLGeocoder()

    @Published var location: CLLocation?
    @Published var placemark: CLPlacemark?

    override init() {
        super.init()
        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
    }

    func geoCode(with location: CLLocation) {

        geoCoder.reverseGeocodeLocation(location) { (placemark, error) in
            if error != nil {
                print(error!.localizedDescription)
            } else {
                self.placemark = placemark?.first
            }
        }
    }
}

extension LocationManager: CLLocationManagerDelegate {

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.first else { return }

        DispatchQueue.main.async {
            self.location = location
            self.geoCode(with: location)
        }

    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        // TODO
    }
}

更新

现在,我已经设置了我的地图视图

但是如何接收我的
LocationManager的数据呢?
didUpdateLocations
方法正在
LocationManager
中工作

我想做的都错了。我想根据当前用户位置在我的
MapView
上设置区域。在UIKit中,它非常简单,但在SwiftUI中,它很奇怪

// Map View

import SwiftUI
import MapKit

struct MapView: UIViewRepresentable {

    @ObservedObject var locationManager: LocationManager = LocationManager()

    class Coordinator: NSObject, MKMapViewDelegate {

        var parent: MapView

        init(_ control: MapView) {
            self.parent = control
        }

    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView(frame: .zero)
        mapView.delegate = context.coordinator
        return mapView
    }

    func updateUIView(_ mapView: MKMapView, context: Context) {
        mapView.showsUserLocation = true
    }

}

struct MapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView()
    }
}

SwiftUI 2

在这种情况下,请改用
StateObject

struct LocationView: View {

    @StateObject var locationManager: LocationManager = LocationManager()
    ...
SwiftUI 1

实际上,
LocationViewModel
在这里是多余的。由于您的
位置管理器
是一个
可观察对象
,您可以在视图中直接使用它,如下所示:

struct LocationView: View {

    @ObservedObject var locationManager: LocationManager = LocationManager()

    var body: some View {
        VStack(alignment: .leading) {
            Text("Latitude: \(locationManager.location.coordinate.latitude.description)")
            Text("Longitude: \(locationManager.location.coordinate.longitude.description)")
        }
    }
}

是的,很好用。此实现是否符合MVVM模式?我正在努力理解SwiftUI的这种模式。然而,在这种情况下,它并不容易使用。这是一个如何在没有虚拟机的情况下实现MVVM的示例。MVVM并不是要有一个名为ViewModel的对象,它并没有SDK或语言绑定支持。我认为这更符合MVVM hi@Jurie,你们找到方法了吗?
// Map View

import SwiftUI
import MapKit

struct MapView: UIViewRepresentable {

    @ObservedObject var locationManager: LocationManager = LocationManager()

    class Coordinator: NSObject, MKMapViewDelegate {

        var parent: MapView

        init(_ control: MapView) {
            self.parent = control
        }

    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView(frame: .zero)
        mapView.delegate = context.coordinator
        return mapView
    }

    func updateUIView(_ mapView: MKMapView, context: Context) {
        mapView.showsUserLocation = true
    }

}

struct MapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView()
    }
}
struct LocationView: View {

    @StateObject var locationManager: LocationManager = LocationManager()
    ...
struct LocationView: View {

    @ObservedObject var locationManager: LocationManager = LocationManager()

    var body: some View {
        VStack(alignment: .leading) {
            Text("Latitude: \(locationManager.location.coordinate.latitude.description)")
            Text("Longitude: \(locationManager.location.coordinate.longitude.description)")
        }
    }
}