I'm dealing with an app where I have to embed a MKMapView (UIKit) into a SwiftUI View. Unfortunately I can't use the implemented Map of SwiftUI, because I have to support clustering (which Map can't do at the moment).
The problem is, that the MKMapView doesn't reflect changes applied to the data source (persons array).

ContentView

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

Implementation of 100 with the help of 101:

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

Demo Model:

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

Please note, that this is a simplified implementation where I removed logic for clustering, etc. to focus on the problem.

enter image description here


If you tap on "Remove Person at index 0" it actually removes the entry at index 0 but unfortunately the map isn't updated. The problem is that updateUIView in MapView doesn't get called and I'm not sure, why this is the case.
Thanks for your help :-)...

推荐答案

两个问题在makeView内创建 map 视图-这是一个设计的地方,在更新中更新注释(无需延迟)这是一个精确绑定更新以更新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相关问答推荐

自定义alert 未执行任何操作

与iPadOS中带有扣件的模式相似的组件是什么?

验证开发人员应用程序证书是否已在您的设备上验证

如何在Android或iPhone上的原生react 中处理其他应用程序通知?

为什么EKEventStore().questFullAccessToEvents()可以与模拟器一起使用,而不能与真实设备一起使用?

如何使用Swift以编程方式更改SVG文件中某些元素的 colored颜色

UIView 阴影不适用于自定义扩展

无法在 CollectionView 中禁用部分弹跳 - 组合布局

List touch Tabbar 时 SwiftUI Tabbar 消失

我可以在 Apple-Watch 上使用 iPhone 的摄像头扫描 SwiftUi 中的二维码(例如用于登录)吗

Xcode 14 弃用了位码 - 但为什么呢?

使用 Vim 代替(或与)Xcode 进行 iOS 开发

Watchkit AppIcon - 名为AppIcon的应用图标集没有任何适用的内容

iOS 7 圆形框架按钮

Xcode 4.2 如何将一个项目包含到另一个项目中?

iOS UITextView 或 UILabel 带有可点击的动作链接

AFNetworking 2.0 向 GET 请求添加标头

Parse for iOS:try 运行应用程序时出错

以编程方式确定 iPhone 是否越狱

为什么我需要@1x、@2x 和@3x iOS 图像?