自定义 MKClusterAnnotation 在 didSet 上失败

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

有一个名为“ClusterAnnotationView”的自定义 MKClusterAnnotation。当我没有预料到时,它会在“assertionFailure”消息中失败。

这是代码:

//MARK: CLUSTER ANNOTATION
final class ClusterAnnotationView: MKAnnotationView {
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
    super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
    collisionMode = .circle
    displayPriority = .defaultHigh
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override var annotation: MKAnnotation? {
    didSet { 
        guard let annotation = annotation as? MKClusterAnnotation else {
            print(annotation)
            assertionFailure("Using ClusterAnnotationView with wrong annotation type")
            return
        }
        self.image = image(count: annotation.memberAnnotations.count)
    }
}

private func image(count: Int) -> UIImage {
    let bounds = CGRect(origin: .zero, size: CGSize(width: 40, height: 40))

    let renderer = UIGraphicsImageRenderer(bounds: bounds)
    return renderer.image { _ in
        //background
        Definitions.Colors.Water.setFill()
        UIBezierPath(ovalIn: bounds).fill()

        // Fill inner circle with white color inset so background shows as border
        UIColor.white.setFill()
        UIBezierPath(ovalIn: bounds.insetBy(dx: 4, dy: 4)).fill()

        // Finally draw count text vertically and horizontally centered
        let attributes: [NSAttributedString.Key: Any] = [
            .foregroundColor: UIColor.black,
            .font: UIFont.boldSystemFont(ofSize: 14)
        ]

        let text = "\(count)"
        let size = text.size(withAttributes: attributes)
        let origin = CGPoint(x: bounds.midX - size.width / 2, y: bounds.midY - size.height / 2)
        let rect = CGRect(origin: origin, size: size)
        text.draw(in: rect, withAttributes: attributes)
    }
}
}

现在,如果我注释掉“assertionFailure(“使用带有错误注释类型的 ClusterAnnotationView”)”,它将显示具有正确编号的集群注释。注释的打印全部打印nil。

查看了 Apple 上关于 Clustering 的文档以及其他一些文档。很多例子都表明它就像我有它一样。

已注册

mapView.register(ClusterAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier)

它的代表就像这样

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    switch annotation {
    case is MapAnnotation:
        let eventAnnotation = MapAnnotationView(annotation: annotation, reuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
        eventAnnotation.delegate = self
        return eventAnnotation
    case is MKClusterAnnotation:
        //return ClusterAnnotationView(annotation: annotation, reuseIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier)
        
        return mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier, for: annotation)
    default:
        return nil
    }
}

我已经尝试了委托中的返回和类的返回,并且只是出队,结果相同。

发生了一些奇怪的事情,因为聚集注释导致地图功能非常滞后,并且它可能与我所看到的问题有关。

有人有任何见解吗?

谢谢

swift mapkit mapkitannotation
1个回答
0
投票

func mapView
至少有一处错误:

对于您要调用的每个不同的

MKAnnotationView
子类,您需要一个不同的reuseIdentifier。
这里发生的事情是随机的:

如果首先调用

mapView.dequeueReusableAnnotationView

,则返回 nil。

nil 意味着 

return mapView.dequeueReusableAnnotationView

启动并创建一个

mapView.register...
实例,一切正常。那就是你看到数字的时候。
一旦您创建了多个

ClusterAnnotationView

,第一个在不再显示时就会被丢弃:

既然你用同样的

MapAnnotationView

reuseIdentifier

将返回类型为 
return mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier, for: annotation)

的对象。

此外,使用 

MapAnnotationView

后,您应该设置出队的

dequeue...
子类对象的注释。
这是您用于每种不同注释类型的模式:

MKMarkerAnnotaionView

您可以对 MapAnnotationView 执行类似的模式。

总是一样的:你尝试出队。如果失败,您将创建一个新的。对于每个不同的

if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: ClusterAnnotationView.REUSEIDENTIFIER) as? TimeAnnotationView { dequeuedView.annotation = clusterAnnotation return dequeuedView } else { let clusterAnnotationView = ClusterAnnotationView(annotation: timeAnnotation, reuseIdentifier: ClusterAnnotationView.REUSEIDENTIFIER) returnclusterAnnotationView }

子类,您使用不同的

MKMarkerAnnotaionView
    

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