SwiftUI MapKit注解优化

nfs0ujit  于 5个月前  发布在  Swift
关注(0)|答案(1)|浏览(75)

我正在做一个项目,其中SwiftUI和MapKit用于在Map上绘制注解。我的解决方案是能够绘制大约1k的注解,但我需要一个解决方案,可以处理至少10k没有滞后或性能问题。
我已经创建了一个示例代码,在Map上绘制一个红色圆圈。您可以通过按“Add”按钮添加注解。还有一个跟踪器类,用于跟踪注解渲染的次数。

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]上,我怀疑我能优化它。
有什么建议吗?

liwlm1x9

liwlm1x91#

群集注解或绘制自定义覆盖。
ForEach循环所有项目是正常的,而不是密集的。只有diff结果用于初始化新对象,如MKMapAnnotation,如果它正在初始化重复的注解,则注解标识可能有问题。
仅供参考SwiftUI“不呈现原生平台框架(AppKit和UIKit)提供的视图,如Web视图、媒体播放器和某些控件。”https://developer.apple.com/documentation/swiftui/imagerenderer

相关问题