ios - UIViewRepresentable - MKMapView 没有得到更新

标签 ios swiftui uikit mkmapview uiviewrepresentable

我正在处理一个应用程序,我必须将 MKMapView (UIKit) 嵌入到 SwiftUI View 中。不幸的是,我不能使用 SwiftUI 的实现 Map,因为我必须支持集群(Map 目前无法支持)。
问题是,MKMapView 不反射(reflect)应用于数据源(persons 数组)的更改。

内容 View

struct ContentView: View {
    @State private var persons: [Person] = [
        .init(
            coordinate: .init(latitude: 50.7123012, longitude: 5.1231021),
            title: "Person 1"
        ),
        .init(
            coordinate: .init(latitude: 49.3123012, longitude: 5.1231021),
            title: "Person 2"
        )
    ]
    
    var body: some View {
        VStack {
            MapView(persons: $persons)
            Button("Remove Person at index 0") {
                persons.remove(at: 0)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

借助 UIViewRepresentable 实现 MKMapView:

struct MapView: UIViewRepresentable {
    @Binding var persons: [Person]
    private let mapView = MKMapView()
    
    init(persons: Binding<[Person]>) {
        self._persons = persons
        // other stuff
    }
    
    func makeUIView(context: Context) -> MKMapView {
        mapView.delegate = context.coordinator
        mapView.register(MKMarkerAnnotationView.self, forAnnotationViewWithReuseIdentifier: "testAnnotation")
        return mapView
    }
    
    func updateUIView(_ uiView: MKMapView, context: Context) {
        DispatchQueue.main.async {
            mapView.removeAnnotations(mapView.annotations)
            mapView.addAnnotations(persons)
        }
    }
}

extension MapView {
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, MKMapViewDelegate {
        
        var parent: MapView
        
        init(_ parent: MapView) {
            self.parent = parent
        }

        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "testAnnotation", for: annotation) as? MKMarkerAnnotationView {
                annotationView.glyphImage = UIImage(systemName: "person")
                return annotationView
            }
            
            return nil
        }
    }
}

演示模型:

class Person: NSObject, MKAnnotation {
    var coordinate: CLLocationCoordinate2D
    let title: String?
    
    init(coordinate: CLLocationCoordinate2D, title: String?) {
        self.coordinate = coordinate
        self.title = title
    }
}

请注意,这是一个简化的实现,我删除了集群等逻辑以专注于问题。

enter image description here


如果您点击“删除索引 0 处的人员”,它实际上会删除索引 0 处的条目,但不幸的是 map 没有更新。问题是 MapView 中的 updateUIView 没有被调用,我不确定为什么会这样。
感谢您的帮助:-)...

最佳答案

两个问题在 makeView 中创建 map View - 这是一个设计的地方,在更新中更新注释(不需要延迟)它是一个调用绑定(bind)更新的地方,以更新 UIView 对应物(所有 UI 失效/刷新都是自动进行的)

所以,这里是固定版本。使用 Xcode 13.4/iOS 15.5 测试

demo

struct MapView: UIViewRepresentable {
    @Binding var persons: [Person]

    init(persons: Binding<[Person]>) {
        self._persons = persons
        // other stuff
    }

    func makeUIView(context: Context) -> MKMapView {

        let mapView = MKMapView()      // << here !!

        mapView.delegate = context.coordinator
        mapView.register(MKMarkerAnnotationView.self, forAnnotationViewWithReuseIdentifier: "testAnnotation")
        return mapView
    }

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

        mapView.removeAnnotations(mapView.annotations)    // << here !!
        mapView.addAnnotations(persons)

    }
}

关于ios - UIViewRepresentable - MKMapView 没有得到更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73040979/

相关文章:

ios - 如何识别 UILabel 的点击来自哪里?

ios - 从 CAAnimation 获取 UIVIew

swift - UIViewController isEditing - 属性观察器不起作用

ios - 读取 NSTimer 子类的 public var valid 失败,错误为 'isValid only defined for abstract class'

ios - xcode 自动调整 xib 的大小在 iphone 6s plus 上不合适

ios - UIWebView 在 iOS 中加载 HTML 后不会返回

ios - 有没有办法从 SwiftUI 中的 ButtonStyle 获取 isDisabled 状态?

iphone - 内存警告后导航 Controller 堆栈问题

ios - SwiftUI |使用 onDrag 和 onDrop 在一个 LazyGrid 中重新排序项目?

button - 如何获取按钮发件人 ID?在 SwiftUI 中