Изменение значения BindableObject, переданного в «MapView: UIViewRepresentable», когда calloutAccessoryControlTapped - PullRequest
1 голос
/ 23 октября 2019

Создание в основном приложения SwiftUI ... Я пытаюсь связать (связать) значение BindableObject в родительском представлении с дочерним представлением MapKit, чтобы при нажатии аннотации (аксессуар выноски) (маленький (i) кнопка на метке аннотации ...

enter image description here

... она изменяет значение $ showDetails на true, которое подключено к«sheet (isPresented: $ showDetails ...)» далее вверх по иерархии представления, которая затем отображает модальное значение:

enter image description here

struct MapView: UIViewRepresentable {

    @Binding var mapSelected: Int
    @Binding var showDetails: Bool    // I WANT TO TOGGLE THIS WHEN CALLOUT ACCESSORY IS TAPPED

    @Binding var location: Location
    @Binding var previousLocation: Location

    @Binding var autoZoom: Bool
    @Binding var autoZoomLevel: Int

    class Coordinator: NSObject, MKMapViewDelegate {

        @Binding var showDetails: Bool

        init(showDetails: Binding<Bool>) {
            _showDetails = showDetails
        }

        func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
            guard let coordinates = view.annotation?.coordinate else { return }
            let span = mapView.region.span
            let region = MKCoordinateRegion(center: coordinates, span: span)
            mapView.setRegion(region, animated: true)
        }

        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            guard let annotation = annotation as? LocationAnnotation else { return nil }
            let identifier = "Annotation"
            var annotationView: MKMarkerAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView
            if annotationView == nil {
                annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
                annotationView?.markerTintColor = UIColor(hex: "#00b4ffff")
                annotationView?.animatesWhenAdded = true
                annotationView?.canShowCallout = true
                annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
            } else {
                annotationView?.annotation = annotation
            }
            return annotationView
        }

    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
            guard let loc = view.annotation as? LocationAnnotation else {
                    print("sorry")
                    return
            }
            print(self.showDetails)     // true, false, true, false, ...
            self.showDetails.toggle()   // THIS DOES TOGGLE, BUT THE VALUE IS NOT OBSERVED BY THE PARENT VIEW
        }
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(showDetails: $showDetails)
    }

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

    func updateUIView(_ uiView: MKMapView, context: Context) {
            switch mapSelected {
                    case 0:
                            uiView.mapType = .standard
                    default:
                            uiView.mapType = .hybrid
            }
            let currentRegion = uiView.region  // get the current region
            var span: MKCoordinateSpan
            var center: CLLocationCoordinate2D
            var newRegion: MKCoordinateRegion

            if currentRegion.span.latitudeDelta == 90.0 && currentRegion.span.longitudeDelta == 180.0 {   // INITIAL
                    span = MKCoordinateSpan(latitudeDelta: 18.0, longitudeDelta: 18.0)
                    center = CLLocationCoordinate2D(latitude: 54.5, longitude: -110)
                    newRegion = MKCoordinateRegion(center: center, span: span)
                    uiView.setRegion(newRegion, animated: true)
            }
            updateAnnotations(from: uiView)
    }

   // ...
}

Что яожидается, что при касании аксессуара выноски происходит переключение showDetails (что и есть), но никакого эффекта не видно в родительском представлении - лист не представлен. Похоже, что привязка не публикует свое новое состояние.

Что я упускаю / делаю неправильно? Я считаю, что интегрировать UIKit с SwiftUI легко, потом сложно, потом легко, а потом невозможно. Помогите, пожалуйста!

...