我正在开发一个项目,其中使用 SwiftUI 和 MapKit 在地图上绘制注释。我拥有的解决方案能够绘制大约 1k 个注释,但我需要一个可以处理至少 10k 个且没有延迟或性能问题的解决方案。
我创建了一个在地图上绘制红色圆圈的示例代码。您可以通过按“添加”按钮添加注释。还有一个跟踪器类,用于跟踪注释渲染的次数。
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()
}
运行上面的代码(Xcode 15.1、iOS 17.2 SDK)会打印以下内容:
Adding
1
2
Adding
1
2
3
Adding
1
2
3
4
这表明每当引入新注释时,系统都会重新渲染所有先前存在的注释。因此,当处理包含 5000 个注释的数据集并引入额外的注释时,整组 5001 个注释都会进行渲染,从而导致滞后和性能问题。
有没有办法优化注释渲染以避免性能问题?
更新:
更改了代码以批量添加注释:
import SwiftUI
import MapKit
struct MapAnnotation {
var id: Int
var location: CLLocationCoordinate2D
// Other Data
}
struct ContentView: View {
@State private var mapAnnotations: [MapAnnotation] = .init()
var body: some View {
ZStack {
Map() {
ForEach(mapAnnotations, id: \.id) { mapAnnotation in
Annotation("", coordinate: mapAnnotation.location, content: {
Circle()
.foregroundStyle(Color.red)
.frame(width: 10)
})
}
}
VStack {
Button(action: {
mapAnnotations.append(.init(id: .random(in: 0 ... Int.max), location: .init(latitude: .random(in: -5 ... 5), longitude: .random(in: -5 ... 5))))
}, label: {
Text("Add One")
.font(.title)
.foregroundStyle(Color.red)
})
Button(action: {
for _ in 0 ... 999 {
mapAnnotations.append(.init(id: .random(in: 0 ... Int.max), location: .init(latitude: .random(in: -5 ... 5), longitude: .random(in: -5 ... 5))))
}
}, label: {
Text("Add Many")
.font(.title)
.foregroundStyle(Color.red)
})
}
.background(Color.black)
}
}
}
#Preview {
ContentView()
}
我在工具中分析了新代码,发现以下趋势:
它表明,当存在 5k 个注释时,在主线程上再添加一个注释大约需要 27 秒,导致无响应。
大部分时间都花在 MapKit
[MKAnnotationView _metricsDidChange]
上,我怀疑我是否可以优化它。请问有什么建议吗?
对注释进行聚类或绘制自定义叠加层