SwiftUI MapKit 注解优化

问题描述 投票:0回答:1

我正在开发一个项目,其中使用 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()
}

我在工具中分析了新代码,发现以下趋势:

image

它表明,当存在 5k 个注释时,在主线程上再添加一个注释大约需要 27 秒,导致无响应。
大部分时间都花在 MapKit

[MKAnnotationView _metricsDidChange]
上,我怀疑我是否可以优化它。

请问有什么建议吗?

ios swift swiftui mapkit mkannotation
1个回答
0
投票

对注释进行聚类或绘制自定义叠加层

© www.soinside.com 2019 - 2024. All rights reserved.