简体   繁体   English

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

[英]SwiftUI: avoid recreating/rerendering view in TabView with MKMapView+UIViewRepresentable

I have a TabView with three tabs, one of which contains a map view that's implemented like this:我有一个带有三个选项卡的 TabView,其中一个包含一个 map 视图,其实现方式如下:

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
        }
    }
}

The tab view is implemented like this:选项卡视图是这样实现的:

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)
}

The problem is that the makeUIView(:context) method is executed every time I switch back to the map tab from one of the other two tabs.问题是每次我从其他两个选项卡之一切换回 map 选项卡时都会执行 makeUIView(:context) 方法。 It appears that the underlying MKMapView instance is deallocated when I switch to another tab, then it's recreated when I switch back.当我切换到另一个选项卡时,似乎底层的 MKMapView 实例被释放,然后当我切换回来时它被重新创建。 In UIKit it doesn't rerender the whole view like that.在 UIKit 中,它不会像那样重新渲染整个视图。 Am I doing something wrong, or is there anything I can do to make sure that the underlying MKMapView instance is retained when I switch back so that it doesn't have to recreate it every single time?我做错了什么,或者我可以做些什么来确保在我切换回来时保留底层的 MKMapView 实例,这样它就不必每次都重新创建它?

You need to store instance of MKMapView for each tab and destroy before you leaving the view because SwiftUI will destroy MapView when it need to render for example the binding vars have changed.您需要为每个选项卡存储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
        }
    }
}

use EnvironmentObject.使用环境对象。 always update it and pass it in TabView {MapView(coordinates: Object.coordinates)}始终更新它并在 TabView {MapView(coordinates: Object.coordinates)} 中传递它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM