diff --git a/darwin/mapkit_flutter/Sources/mapkit_flutter/Annotations/AnnotationController.swift b/darwin/mapkit_flutter/Sources/mapkit_flutter/Annotations/AnnotationController.swift index eb8a3be..a1663d3 100644 --- a/darwin/mapkit_flutter/Sources/mapkit_flutter/Annotations/AnnotationController.swift +++ b/darwin/mapkit_flutter/Sources/mapkit_flutter/Annotations/AnnotationController.swift @@ -86,9 +86,15 @@ extension MapKitViewHost { } func annotationsToAdd(_ annotations: [PlatformAnnotation]) { - for annotation in annotations { - addAnnotation(FlutterAnnotation(fromPlatform: annotation)) + let toAdd = annotations.map(FlutterAnnotation.init(fromPlatform:)) + let stale = toAdd.compactMap { self.annotationsById.removeValue(forKey: $0.id) } + if !stale.isEmpty { + self.mapView.removeAnnotations(stale) } + for annotation in toAdd { + self.annotationsById[annotation.id] = annotation + } + self.mapView.addAnnotations(toAdd) } func annotationsToChange(_ annotations: [PlatformAnnotation]) { @@ -107,8 +113,9 @@ extension MapKitViewHost { } func annotationsToRemove(_ annotationIds: [String]) { - for annotationId in annotationIds { - removeAnnotation(id: annotationId) + let toRemove = annotationIds.compactMap { self.annotationsById.removeValue(forKey: $0) } + if !toRemove.isEmpty { + self.mapView.removeAnnotations(toRemove) } } diff --git a/darwin/mapkit_flutter/Sources/mapkit_flutter/Overlays/FlutterOverlay.swift b/darwin/mapkit_flutter/Sources/mapkit_flutter/Overlays/FlutterOverlay.swift index b09612c..445f14e 100644 --- a/darwin/mapkit_flutter/Sources/mapkit_flutter/Overlays/FlutterOverlay.swift +++ b/darwin/mapkit_flutter/Sources/mapkit_flutter/Overlays/FlutterOverlay.swift @@ -15,20 +15,22 @@ protocol FlutterOverlay: MKOverlay { extension MKMapView { /// Adds an overlay, using `zIndex` as an ordering hint within its level: - /// the overlay lands after every existing Flutter overlay whose zIndex is - /// `<=` its own, so equal indices preserve insertion order. The insertion - /// index is clamped to the level's array bounds. + /// the overlay lands directly before the first Flutter overlay whose + /// zIndex is greater than its own, so equal indices preserve insertion + /// order. Non-Flutter peers (tile overlays) carry no zIndex and never + /// shift the position; with no higher-zIndex peer the overlay is appended + /// on top of the level. func addFlutterOverlay(_ overlay: any FlutterOverlay) { let level = overlay.overlayLevel let peers = self.overlays(in: level) - let index = peers - .compactMap { $0 as? any FlutterOverlay } - .filter { $0.zIndex <= overlay.zIndex } - .count - if index >= peers.count { - addOverlay(overlay, level: level) - } else { + let index = peers.firstIndex { peer in + guard let flutterPeer = peer as? any FlutterOverlay else { return false } + return flutterPeer.zIndex > overlay.zIndex + } + if let index { insertOverlay(overlay, at: index, level: level) + } else { + addOverlay(overlay, level: level) } }