I am working on a project where SwiftUI and MapKit is used to draw annotations on a Map. The solution I have is able to draw about 1k annotations, but I need a solution that can handle at least 10k without lag or performance issues.
I have created a sample code that draws a red circle on a Map. You can add annotation by pressing the ‘Add’ button. There is also a Tracker class used to track the number of annotation renders occurred.
import SwiftUI
import MapKit
struct MapAnnotation {
var id: Int
var location: CLLocationCoordinate2D
}
class Tracker {
var done = 0
static let shared = Tracker()
}
struct ContentView: View {
@State private var mapAnnotations: [MapAnnotation] = .init()
var body: some View {
ZStack {
Map() {
ForEach(mapAnnotations, id: \.id) { intensity in
Annotation("", coordinate: intensity.location, content: {
Circle()
.foregroundStyle(Color.red)
.frame(width: getWidth(intensity: intensity))
})
}
}
Button(action: {
print("Adding")
Tracker.shared.done = 0
mapAnnotations.append(.init(id: .random(in: 0 ... Int.max), location: .init(latitude: .random(in: -5 ... 5), longitude: .random(in: -5 ... 5))))
}, label: {
Text("Add")
.font(.title)
.foregroundStyle(Color.red)
})
}
}
private func getWidth(intensity: MapAnnotation) -> CGFloat {
Tracker.shared.done += 1
print(Tracker.shared.done)
return 10
}
}
#Preview {
ContentView()
}
Running the code (Xcode 15.1, iOS 17.2 SDK) above prints the following:
Adding
1
2
Adding
1
2
3
Adding
1
2
3
4
This indicates that whenever a new annotation is introduced, the system re-renders all previously existing annotations. Consequently, when handling a dataset of 5000 annotations and introducing an additional one, the entire set of 5001 annotations undergoes rendering, leading to lag and performance issues.
Is there any way to optimise annotation rendering to avoid performance issues?