首页 > 解决方案 > 渲染自定义注释时 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
        }
    }
}

标签: swiftannotationsrenderingmapkitfreeze

解决方案


推荐阅读