我正在使用一个 SwiftUI 视图,其中包含带有大量注释(范围从 30 到 100)的地图。除此之外,还有一个特定的注释,该注释会根据用户从列表中的选择而变化。列表选择可能会快速更改,可能每秒最多更改 10 次。
更新所选注释时,地图视图上的所有注释似乎都会重新加载。这会导致 CPU 使用率高和屏幕刷新率显着下降,尤其是在快速选择更改期间。
如何优化它,以便在更改 selectedAnnotation 时仅重新加载地图视图中选定的注释而不是所有注释?
以下是相关伪代码:
@State var annotations = [MKAnnotation]()
@State var selectedAnnotation: MKAnnotation?
Map {
ForEach(annotations.indices, id: \.self) { idx in
let anno = annotations[idx]
Annotation("", coordinate: anno.coordinate) {
Circle()
.stroke(.black, lineWidth: 4)
.fill(.white)
.frame(width: 8, height: 8)
}
}
if let selectedAnnotation {
Annotation("", coordinate: selectedAnnotation.coordinate) {
Circle()
.stroke(.orange, lineWidth: 4)
.fill(.white)
.frame(width: 16, height: 16)
}
} else {
EmptyMapContent()
}
}
import SwiftUI
import MapKit
struct Point: Identifiable {
let id = UUID()
var coordinate: CLLocationCoordinate2D
}
struct MapKitIssuesView: View {
@State var points: [Point] = []
@State var selectedCoord: CLLocationCoordinate2D?
var body: some View {
ZStack {
Map {
ForEach(points) { point in
let _ = print("reloaded \(point) at \(Date())")
Annotation("", coordinate: point.coordinate) {
Circle()
.fill(.black)
.frame(width: 4, height: 4)
}
}
if let selectedCoord {
Annotation("", coordinate: selectedCoord) {
Circle()
.stroke(.orange, lineWidth: 4)
.fill(.white)
.frame(width: 16, height: 16)
}
} else {
EmptyMapContent()
}
}
.mapStyle(.standard(pointsOfInterest: .excludingAll))
.onAppear {
for lat in 30 ... 45 {
for lon in -137 ... -79 {
points.append(.init(coordinate: .init(latitude: Double(lat), longitude: Double(lon))))
}
}
}
.onDisappear {
points.removeAll()
}
VStack {
Spacer()
Button(action: {
selectedCoord = .init(latitude: .random(in: 30 ..< 45), longitude: .random(in: -137 ..< -79))
}, label: {
Text("Change Selection")
})
.tint(.white)
}
}
}
}
#Preview {
MapKitIssuesView()
}
这是我的测试代码
import Foundation
import SwiftUI
import MapKit
struct ContentView: View {
var body: some View {
MapKitIssuesView()
}
}
struct Point: Identifiable {
let id = UUID()
var coordinate: CLLocationCoordinate2D
}
struct MapKitIssuesView: View {
@State var coordinates: [Point] = []
@State var selectedCoord: CLLocationCoordinate2D?
var body: some View {
ZStack {
Map {
ForEach(coordinates) { p in
Annotation("", coordinate: p.coordinate) {
Circle()
.fill(.black)
.frame(width: 4, height: 4)
}
}
if let selectedCoord {
Annotation("", coordinate: selectedCoord) {
Circle()
.stroke(.orange, lineWidth: 4)
.fill(.orange)
.frame(width: 16, height: 16)
}
}
}
.mapStyle(.standard(pointsOfInterest: .excludingAll))
.onAppear {
for lat in 30 ... 45 {
for lon in -137 ... -79 {
coordinates.append(
Point(coordinate: CLLocationCoordinate2D(latitude: Double(lat), longitude: Double(lon))))
}
}
}
.onDisappear {
// coordinates.removeAll()
}
VStack {
Spacer()
Button("Change Selection") {
selectedCoord = .init(latitude: .random(in: 30 ..< 45),
longitude: .random(in: -137 ..< -79))
}
.buttonStyle(.bordered)
.tint(.red)
}
}
}
}