由于EnvironmentObject是只读的,因此尝试从子视图向父视图分配@EnvironmentObject失败

问题描述 投票:0回答:1

我有一个基于地图的应用,所以我想为地图的当前位置提供一个应用范围的属性。

我正在SceneDelegate中对其进行初始化

    let currentPosition = CurrentPosition()
    let mainView = MainView(appState: AppState(), selectedWeatherStation: nil).environmentObject(currentPosition)

我在MainView中将其声明为@EnvironmentObject

struct MainView: View {
    @State var appState: AppState
    @State var selectedWeatherStation: WeatherStation? = nil

    @EnvironmentObject var currentPosition: CurrentPosition

并且我将其注入我的UIViewRepresentable孩子中

 MapView(weatherStations: $appState.appData.weatherStations,
                    selectedWeatherStation: $selectedWeatherStation).environmentObject(currentPosition)
                    .edgesIgnoringSafeArea(.vertical)

MapView

struct MapView: UIViewRepresentable {
    @Binding var weatherStations: [WeatherStation]
    @Binding var selectedWeatherStation: WeatherStation?

    @EnvironmentObject var currentPosition: CurrentPosition

我有一个最终的子类

final class Coordinator: NSObject, MKMapViewDelegate {
        @EnvironmentObject var currentPosition: CurrentPosition

作为我的mapview委托,我要在其中更新currentPosition

  func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
            currentPosition = CurrentPosition(northEast: mapView.northEastCoordinate, southWest: mapView.southWestCoordinate)
        }

但是此作业currentPosition = CurrentPosition(northEast: mapView.northEastCoordinate, southWest: mapView.southWestCoordinate)会抛出一个错误Cannot assign to property: 'currentPosition' is a get-only property而且我真的不知道我在做什么错。

目的是每次用户移动地图时都会更新位置,以便我可以使用当前坐标向我的API执行请求。

CurrentPosition声明如下

class CurrentPosition: ObservableObject {
    @Published var northEast = CLLocationCoordinate2D()
    @Published var southWest = CLLocationCoordinate2D()

    init(northEast: CLLocationCoordinate2D = CLLocationCoordinate2D(), southWest: CLLocationCoordinate2D = CLLocationCoordinate2D()) {
        self.northEast = northEast
        self.southWest = southWest
    }
}
swift mapkit swiftui combine uiviewrepresentable
1个回答
0
投票

[您需要center设置地图位置,NE和SW角是主观的,因为它们会随着屏幕尺寸,位置(横向与纵向),缩放等而变化。

您可以从地图的centerspan中计算它们。

尝试启动此代码,以便您可以了解它们如何相互影响。

import SwiftUI
import MapKit

class MapViewController: ObservableObject {

    @Published var center: CLLocationCoordinate2D = CLLocationCoordinate2D()
    @Published var latitudeDelta:CLLocationDegrees = CLLocationDegrees()
    @Published var longitudeDelta:CLLocationDegrees = CLLocationDegrees()
    var southWest: CLLocationCoordinate2D{
        get{return CLLocationCoordinate2D(latitude: -(latitudeDelta/2) + center.latitude, longitude: -(longitudeDelta/2) + center.longitude)}
    }
    var northEast: CLLocationCoordinate2D{
        get{return CLLocationCoordinate2D(latitude: (latitudeDelta/2) + center.latitude, longitude: (longitudeDelta/2) + center.longitude)}
    }
    func resetCenter(){
        center = CLLocationCoordinate2D()
    }
}
struct CustomMapView: View {
    @ObservedObject var mapCont: MapViewController = MapViewController()
    @State var refresh: Bool = false
    var body: some View {
        VStack {
            CustomMap(mapCont: mapCont, refresh: $refresh)
            HStack {
                VStack {
                    HStack{
                        Text(String(format: "Center Lat: %.4f", self.mapCont.center.latitude))
                        Spacer()
                        Text(String(format: "Center Lon: %.4f", self.mapCont.center.longitude))
                    }
                    HStack{
                        Text("LatDelta = \(self.mapCont.latitudeDelta)")
                        Spacer()
                        Text("LonDelta = \(self.mapCont.longitudeDelta)")
                    }
                    HStack{
                        Text("SW Lat = " + String(format: " %.4f",self.mapCont.southWest.latitude))
                        Spacer()
                        Text("SW Lat =" + String(format: " %.4f",self.mapCont.southWest.longitude))
                    }
                    HStack{
                        Text("NE Lat = " + String(format: " %.4f",self.mapCont.northEast.latitude))
                        Spacer()
                        Text("NE Lat = "  + String(format: " %.4f",self.mapCont.northEast.longitude))
                    }
                }
                Spacer()
                Button("Reset") {
                    print("resetButton")
                    self.mapCont.resetCenter()
                    self.refresh.toggle()
                    print("resetButton :: center = \(self.mapCont.center)")
                }
            }.padding(.horizontal)
        }
    }
}
struct CustomMap: UIViewRepresentable {
    var mapCont: MapViewController
    @Binding var refresh: Bool
    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()
        mapView.delegate = context.coordinator
        return mapView
    }

    func updateUIView(_ uiView: MKMapView, context: Context) {
        print("update")
        uiView.centerCoordinate = self.mapCont.center
    }

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

    class Coordinator: NSObject, MKMapViewDelegate {
        var parent: CustomMap
        func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
            self.parent.mapCont.center = mapView.centerCoordinate
            self.parent.mapCont.latitudeDelta =  mapView.region.span.latitudeDelta
            self.parent.mapCont.longitudeDelta = mapView.region.span.longitudeDelta
        }

        init(_ parent: CustomMap) {
            self.parent = parent
        }
    }
}
struct CustomMapView_Previews: PreviewProvider {
    static var previews: some View {
        CustomMapView()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.