更改后不会更新带有MKMapView地图的SwiftUI

时间:2020-03-20 20:27:29

标签: ios xcode swiftui uiviewrepresentable

我有一个SwiftUI应用程序,其中包括MKMapView UIViewRepresentable。地图功能 允许用户通过创建航点来选择自己的路径。基本逻辑 效果很好,但是当某些更改发生时,我无法重绘地图 制作。具体来说,用户可以点击现有旅行/地图的路标注释,然后 选择在点击的项目之后添加新的航路点,或删除点击的项目。 奇怪的是,删除工作正常,但插入操作不起作用 导致重绘地图(视图中的计算距离也未更新)。 设计是一个基本的清单/详细信息,其中清单是行程和 详细信息是旅行的mapView。数据存储在核心数据中,并且 确实在删除或插入时正确更新, 但是同样,对于插入,地图不会更新,直到行程结束 然后重新打开。

对于插入,我在地图上覆盖了一个SwiftUI视图,该视图 包含一个目标(在地图中心)和一个用于插入该项目的按钮。的 用户移动地图,使新的航点位于目标下方,然后点按“插入”按钮。一世 希望在插入航路点后(通过按钮)重绘地图。

我想基本知识-有没有办法强制MKMapKit协议调用 func updateUIView(_视图:MKMapView,上下文:Context){} 从不是UIViewRepresentable的视图 和/或,如何在SwiftUI文件中获取对mapview的引用,该引用会调用 详情。似乎向后绑定应该起作用,但我没有成功。

此SwiftUI文件称为DetailMapView,它是UIViewRepresentable。 点击按钮会将坐标插入Core Data。

struct ComboDetailMapView: View {

    @ObservedObject var udm: UserDefaultsManager
    @Environment(\.presentationMode) var presentationMode
    @State var thisMap: MKMapView?

    let generator = UINotificationFeedbackGenerator()

    var aTrip: Trip?
    var body: some View {
        GeometryReader { geo in
            ZStack {
                ZStack {
                    VStack {
                        Text(self.aTrip?.name ?? "Unknown Map Name")
                            .padding(.top, -50)
                            .padding(.bottom, -20)
                        DetailMapView(udm: self.udm, aTrip: self.aTrip)
                            .padding(.top, -20)
                    }//vstack
                    VStack {
                        Spacer()
                        ZStack {
                            RoundedRectangle(cornerRadius: 20)
                                .fill(Color.white).opacity(0.8)
                                .frame(width: geo.size.width - 20, height: 100)
                            Text(self.udm.tripTimeAndDistance)
                                //...bunch of modifiers
                        }
                        .padding(.bottom, 20)
                    }//vstack

                }//to put time and distance on top

                ZStack {
                    VStack {
                        Spacer()
                        HStack {
                            Spacer()
                            Button(action: {
                                self.generator.notificationOccurred(.success)                                
                                self.udm.showAddWaypointControls.toggle()
                                guard let guardTrip = self.aTrip else { return }

                                DetailMapView(udm: self.udm).insertNewWaypoint(insertTrip: guardTrip, centerCoordinate: self.udm.pubCenterCoordinate, name: "Center", subtitle: "Center", pinText: "Center", wayPointSequence: self.udm.insertSequenceNumber + 1)

                            }) {
                                Image(systemName: "plus")
                            }
                            //...bunch of modifiers
                        }
                    }//vstack

                    Circle()
                        //...modifiers

                }//button and circle zstack
                    .offset(x: self.udm.showAddWaypointControls ? 0 : screen.width)
                    .animation(.easeInOut(duration: 1.0))
            }//zstack
        }//geo
    }//body
}

DetailMapView:

struct DetailMapView: UIViewRepresentable {

    let kAppDelegate = UIApplication.shared.delegate as! AppDelegate

    @Environment(\.presentationMode) var presentationMode
    @ObservedObject var udm: UserDefaultsManager
    //bunch of @State variables

    var aTrip: Trip?

    class Coordinator: NSObject, MKMapViewDelegate {
        var parent: DetailMapView

        init(_ parent: DetailMapView) {
            self.parent = parent
        }

        func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
            parent.udm.pubCenterCoordinate = mapView.centerCoordinate
        }

        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            let identifier = "CRSAnnotationView"
            //...more code - all this works
            return crsAnnotationView
        }//viewfor

        func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {

            if control == view.leftCalloutAccessoryView {
            //...more code - all this works

            } else if control == view.rightCalloutAccessoryView {

                mapView.removeAnnotations(parent.annotations)
                parent.annotations = []

                //this displays the overlay with the target and the button to add the waypoint
                parent.udm.showAddWaypointControls.toggle()

                guard let guardTrip = parent.aTrip else { return }
                for wp in guardTrip.waypoints {
                    //...code to sequence the waypoints in the Core Data NSSet - this all works
                }//for wp in parent.aTrip!.waypoints

            }//else if control == else if control 

        }//annotationView

        func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
            let renderer = MKPolylineRenderer(polyline: overlay as! MKPolyline)
            renderer.strokeColor = UIColor.blue
            renderer.lineWidth = 4.0

            return renderer
        }//rendererFor

    }//class coordinator

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

    func makeUIView(context: Context) -> MKMapView {

        //...housekeeping code for distance and time display - all works

        self.udm.showAddWaypointControls = false

        let mapView = MKMapView()
        mapView.showsUserLocation = true
        mapView.delegate = context.coordinator
        udm.tripTimeAndDistance = "Calculating..."

        return mapView
    }

//This is called for deletions, but not for insertions:
    func updateUIView(_ view: MKMapView, context: Context) {
        redrawTheMap(trip: aTrip, mapView: view)
    }//updateUIView


    func doOneWaypointPolylineCallback(view: MKMapView, source: CLLocationCoordinate2D, destination: CLLocationCoordinate2D, callback: @escaping (Double, Double) -> Void) {
        //this code gets distance and time for each segment and works
    }//doOneWaypointPolylineCallback

    func modifyTheWaypointList(trip: Trip?, mapView: MKMapView, view: MKAnnotationView) {
        //this code deleted the waypoint from Core Data and works
    }//modifyWayList

    func redrawTheMap(trip: Trip?, mapView: MKMapView) {
        //...this code cycles through the waypoints to add annotations and overlays - it works
    }//redrawTheMap

}//struct DetailMapView

任何指导将不胜感激。

Xcode版本11.3.1(11C504

0 个答案:

没有答案