ios - SwiftUI:避免使用 MKMapView+UIViewRepresentable 在 TabView 中重新创建/重新渲染 View

标签 ios mapkit swiftui

我有一个包含三个选项卡的 TabView,其中一个包含这样实现的 map View :

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

标签 View 是这样实现的:

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

问题是每次我从其他两个选项卡之一切换回 map 选项卡时都会执行 makeUIView(:context) 方法。当我切换到另一个选项卡时,底层 MKMapView 实例似乎被释放,然后当我切换回来时它被重新创建。在 UIKit 中,它不会像那样重新渲染整个 View 。我是不是做错了什么,或者我能做些什么来确保在我切换回来时保留底层 MKMapView 实例,这样它就不必每次都重新创建它?

最佳答案

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

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

关于ios - SwiftUI:避免使用 MKMapView+UIViewRepresentable 在 TabView 中重新创建/重新渲染 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58093295/

相关文章:

ios - 如何修复 "Instance member ' coordinate' cannot be used on type 'MKMapPoint' “Swift 5.0 中的错误

ios - 子类化 MKMapView 并使其成为 mapview 委托(delegate),同时仍然允许其他委托(delegate)

ios - 如何为在 iPad 上运行的 iPhone SwiftUI 应用程序锁定纵向方向?

ios:为什么媒体播放器静音?

ios - 知道所有回调都已使用 libevent 和 bufferevent_free 运行

ios - 向多个 subview Controller 发送消息的最佳方式

objective-c - 如何按固定百分比扩展 MKMapRect?

ios - 传递依赖于另一个绑定(bind)的绑定(bind)

swiftui - 如何使用 SwiftUI 显示搜索栏

iphone - i386 defacebookComposerViewController 架构的 undefined symbol