SwiftUI:避免使用MKMapView + UIViewRepresentable在TabView中重新创建/渲染视图

时间:2019-09-25 07:30:17

标签: ios mapkit swiftui

我有一个带有三个标签的TabView,其中一个包含这样实现的地图视图:

struct MapView: UIViewRepresentable {
    let region: MKCoordinateRegion
    let animatedRegion: Bool

    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView(frame: .zero)
        mapView.delegate = context.coordinator
        mapView.showsUserLocation = true
        mapView.setRegion(region, animated: animatedRegion)
        return mapView
    }

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

    func updateUIView(_ mapView: MKMapView, context: Context) {

    }

    class Coordinator: NSObject, MKMapViewDelegate {
        var control: MapView

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

标签视图的实现方式如下:

TabView(selection: $selection) {
    MapView(/* params */)
        .tabItem {
            Image(systemName: "1.square.fill")
            Text("map")
        }.tag(1)
    Text("Screen #2")
        .tabItem {
            Image(systemName: "2.square.fill")
            Text("2")
        }.tag(2)
    Text("Screen #3")
        .tabItem {
            Image(systemName: "3.square.fill")
            Text("3")
        }.tag(3)
}

问题在于,每次我从其他两个选项卡之一切换回地图选项卡时,都会执行makeUIView(:context)方法。看来,当我切换到另一个选项卡时,基础MKMapView实例已被释放,而当我切换回该选项卡时,将重新创建该实例。在UIKit中,它不会像这样重新渲染整个视图。我是在做错什么,还是可以做些什么来确保在我切换回原样时保留基础的MKMapView实例,这样就不必每次都重新创建它了?

2 个答案:

答案 0 :(得分:2)

您需要为每个选项卡存储MKMapView的实例,并在离开视图之前销毁,因为SwiftUI将在需要渲染(例如绑定变量已更改)时销毁MapView。

struct MapView: UIViewRepresentable {
    @Binding var currentTab: Int
    static private var mapViews = [Int: MKMapView]()

    let region: MKCoordinateRegion
    let animatedRegion: Bool

    func makeUIView(context: Context) -> MKMapView {
        guard MapView.mapViews[currentTab] != nil else { return MapView.mapViews[currentTab]! }

        let mapView = MKMapView(frame: .zero)
        mapView.delegate = context.coordinator
        mapView.showsUserLocation = true
        mapView.setRegion(region, animated: animatedRegion)

        MapView.mapViews[currentTab] = mapView

        return mapView
    }

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

    func updateUIView(_ mapView: MKMapView, context: Context) {

    }

    class Coordinator: NSObject, MKMapViewDelegate {
        var control: MapView

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

答案 1 :(得分:-2)

使用EnvironmentObject。始终对其进行更新并在TabView {MapView(coordinates:Object.coordinates)}

中传递