swift - 渲染自定义注释时 MKMapView 冻结
问题描述
大约有1500个带有值和图像的自定义注释。
我知道这种定制的实时渲染代价很高,但是在viewfor 注释期间UI 会冻结(一段时间)(当用户移动地图时,每个注释都需要时间来渲染,而且它会缩小更多注释出现,UI 冻结的时间越长)。
在 android 上的同一个应用程序中,我设法通过将所有注释聚集到看不见的地方来改进这一点,只在它们变得可见时才渲染它们,而不冻结地图。
渲染必须在主线程之外的后台进行。
也欢迎其他建议。
一些代码:viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
mapView.register(CustomPinAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
// mapView.register(CustomPinAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier)
... configureDatabase()
... loadMapMap()
... loadAnnotations()
}
更多代码:viewfor 注释
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isMember(of: MKUserLocation.self) { return nil }
if annotation is MKClusterAnnotation { return nil }
guard let customAnnotation = annotation as? CustomPin else { return nil }
... GET ANNOTATION INFO ...
let reusePin = preco+stared+fechado+excluido+publico+particular
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reusePin) as? CustomPinAnnotationView
if pinView == nil { pinView = CustomPinAnnotationView(annotation: annotation, reuseIdentifier: reusePin) }
else { return pinView }
... RENDER CUSTOM ANNOTATION IMAGE ...
UIGraphicsEndImageContext()
pinView?.canShowCallout = true
pinView?.centerOffset = CGPoint(x: size.width / 5 , y: -size.height / 5)
print("=", terminator:"")
return pinView
}
CustomPinAnnotationView.swift
import Foundation
import UIKit
import MapKit
class CustomPinAnnotationView: MKAnnotationView {
private var observerContext = 0
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
clusteringIdentifier = "cluster"
collisionMode = .circle
centerOffset = CGPoint(x: 0, y: -10) // Offset center point to animate better with marker annotations
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var annotation: MKAnnotation? {
willSet {
removeObserverIfAny()
}
didSet {
if let annotation = annotation as? CustomPin {
annotation.addObserver(self, forKeyPath: #keyPath(CustomPin.subtitle), context: &observerContext)
}
}
}
deinit {
removeObserverIfAny()
}
private func removeObserverIfAny() {
if let oldAnnotation = annotation as? CustomPin {
oldAnnotation.removeObserver(self, forKeyPath: #keyPath(CustomPin.subtitle))
}
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard context == &observerContext else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
}
}
解决方案
推荐阅读
- python - Python attrs/cattrs 使用冻结的 attrs 类作为字典键序列化字典
- java - quarkus 和 jwt 令牌、application.properties var 不起作用
- c - 打开和关闭 PIC24 上的 LED。我没有看到代码有问题。但是状态机似乎没有正确执行
- python - 在 Airflow subdag 中访问上下文
- python - 应用列中包含列表的数据框
- c# - Socket.Disconnect(true) 有什么意义?
- ios - 使用本机反应播放 .Flac 或 .Alac 文件,甚至可以在 iPhone 上使用吗?
- sql - Databricks (Azure) SQL 中的 For/Loop/While
- firebase - Firestore 规则拆分自定义令牌并查看它是否匹配
- html - Safari:可滚动 div 中的滚动条颜色错误