SwiftUI будет уведомлен, когда все свойства ObservableObject обновлены - PullRequest
1 голос
/ 09 февраля 2020

У меня есть ObservableObject


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


    init(northEast: CLLocationCoordinate2D = CLLocationCoordinate2D(), southWest: CLLocationCoordinate2D = CLLocationCoordinate2D()) {
        self.northEast = northEast
        self.southWest = southWest
    }

    func updateCoordinates(from mapView: MKMapView) {
        self.northEast = mapView.northEastCoordinate
        self.southWest = mapView.southWestCoordinate
    }
}

, который я хочу обновить из MapView

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

    @EnvironmentObject var currentPosition: CurrentPosition

    func makeUIView(context: Context) -> MKMapView {
        let map = MKMapView()
        map.showsUserLocation = true
        map.delegate = context.coordinator
        return map
    }

    func updateUIView(_ uiView: MKMapView, context: Context) {
        updateAnnotations(from: uiView)
    }

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


    final class Coordinator: NSObject, MKMapViewDelegate {
        var control: MapView

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

        func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
            control.currentPosition.updateCoordinates(from: mapView)
        }

    }
}

и передать его в AppState объект

 MapView(weatherStations: $appState.appData.weatherStations,
                        selectedWeatherStation: $selectedWeatherStation).environmentObject(self.currentPosition)
                    .edgesIgnoringSafeArea(.vertical).onReceive(currentPosition.objectWillChange) { () in
                        self.appState.currentPosition = self.currentPosition
                }}

, который, в свою очередь, передает его моему клиенту API

class AppState: ObservableObject {
    @Published var appData = AppData(weatherStations: [WeatherStation]())
    var currentPosition: CurrentPosition! {
        didSet {
            api.currentPosition = self.currentPosition
        }
    }
}

Мои проблемы заключаются в том, что оно передается каждый раз, когда обновляется одно из моих CurrentPosition свойств, то есть сначала оно передается при получении northEast обновляется, чем когда southWest обновляется.

Как я могу передать его только один, когда оба закончили обновление?

1 Ответ

1 голос
/ 10 февраля 2020

Самый простой способ - сложить его в одно свойство с помощью вторичного struct, например, так:

struct MapCoordinateSpan {
  let northEast: CLLocationCoordinate2D
  let southWest: CLLocationCoordinate2D
}

и изменить ваш CurrentPosition, чтобы он выглядел так:

class CurrentPosition: ObservableObject {
    @Published var span: MapCoordinateSpan

    init(northEast: CLLocationCoordinate2D = CLLocationCoordinate2D(), southWest: CLLocationCoordinate2D = CLLocationCoordinate2D()) {
        self.span = MapCoordinateSpan(northEast: northEast, southWest: southWest)
    }

    func updateCoordinates(from mapView: MKMapView) {
        self.span = MapCoordinateSpan(northEast: mapView.northEastCoordinate, southWest: mapView.southWestCoordinate)
    }
}

Затем привяжите к свойству span и вытащите оттуда координаты.

...