群集在iOS 13中无法正常工作

时间:2019-11-01 09:19:47

标签: swift mkmapview mkannotation mkannotationview mkmapviewdelegate

我正在对注释进行聚类。

下面的代码可以正常工作,并且可以在iOS 11和iOS 12中正确聚集点。

这无法聚集点,从而降低了iOS 13中的点。

我没有使用任何beta版本。

TTMapView类是MKMapView的包装器。

class TTMapView: UIView {

    var mapView = MKMapView()
    private var mapObjects: Dictionary<TTShape, MKShape?> = [:]
    private var _isClusteringEnabled = true

    func addMarker(_ marker: TTPoint) -> TTPoint {
        removeMarker(marker)
        let coordinate = marker.coordinate
        let pointAnnotation = MKPointAnnotation()
        pointAnnotation.coordinate = convertTTCoordinateToCLLocationCoordinate2D(coordinate)
        pointAnnotation.title = marker.title
        pointAnnotation.subtitle = marker.subtitle
        mapObjects.updateValue(pointAnnotation, forKey: marker)
        mapView.addAnnotation(pointAnnotation)
        return marker
    }
}

extension TTMapView: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation is MKUserLocation {
            return nil
        }

        if _isClusteringEnabled {
            let point = mapObjects.filter ({ $0.value === annotation }).first?.key as? TTPoint
            print("point ", point)
            return TTClusterAnnotationView(annotation: annotation, reuseIdentifier: TTClusterAnnotationView.ReuseID, image: point?.image, color: point?.tintColor)
        } else {
            let reuseId = "simplePin"
            var pinAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
            if pinAnnotationView == nil {
                pinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
                pinAnnotationView?.isDraggable = true
                pinAnnotationView?.canShowCallout = true
            }
            return pinAnnotationView
        }
    }
}

class TTClusterAnnotationView: MKMarkerAnnotationView {

    /// Use this Id for setting annotation
    static let ReuseID = "clusterAnnotation"

    init(annotation: MKAnnotation?, reuseIdentifier: String?, image: UIImage?, color: UIColor? = nil) {
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
        // Enable clustering by just setting the clusteringIdentifier
        clusteringIdentifier = "clusteringIdentifier"
        glyphImage = image
        glyphTintColor = color
    }

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

    override func prepareForDisplay() {
        super.prepareForDisplay()
        displayPriority = .required
    }
}

1 个答案:

答案 0 :(得分:0)

进行集群注释视图(这是集群的注释视图,不要与具有clusteringIdentifier的现有注释视图混淆,我将其重命名为CustomAnnotationView以避免混淆)的displayPriority中的.required

class CustomClusterAnnotationView: MKMarkerAnnotationView {
    override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
        displayPriority = .required
    }

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

    override var annotation: MKAnnotation? {
        didSet {
            displayPriority = .required
        }
    }
}

然后注册该课程:

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

然后使用它:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation is MKUserLocation {
        return nil
    }

    if annotation is MKClusterAnnotation {
        return nil
    }

    ...
}

一些无关的发现:

  1. 我建议您仅将图像和颜色属性添加到自定义注释类型中,而不要使用viewFormapObjects进行过滤。所以:

    class CustomAnnotation: MKPointAnnotation {
        let image: UIImage
        let color: UIColor
    
        init(coordinate: CLLocationCoordinate2D, title: String?, image: UIImage, color: UIColor) {
            self.image = image
            self.color = color
            super.init()
            self.coordinate = coordinate
            self.title = title
        }
    }
    

    然后,如果您使用的不是MKPointAnnotation,则自定义注释视图可以将颜色和图像信息直接从注释中拉出。

    class CustomAnnotationView: MKMarkerAnnotationView {
        static let reuseID = "CustomAnnotationView"
    
        override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
            super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
            updateForAnnotation()
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        override var annotation: MKAnnotation? {
            didSet {
                updateForAnnotation()
            }
        }
    }
    
    private extension CustomAnnotationView {
        func updateForAnnotation() {
            clusteringIdentifier = "CustomAnnotationView"
            displayPriority = .required
            if let annotation = annotation as? CustomAnnotation {
                glyphImage = annotation.image
                glyphTintColor = annotation.color
            } else {
                glyphImage = nil
                glyphTintColor = nil
            }
        }
    }
    

    请注意,在上方,我要重置didSet的{​​{1}}中的群集标识符,图像,字形等。这样可以重用注释视图。 (请参阅下一点。)

  2. 引脚注释视图的重用逻辑不正确。如果启用了群集,则根本不会进行重用。如果定位到iOS 11及更高版本,我将使用annotation来为您解决所有这些问题。因此,我可以注册此重用ID:

    dequeueReusableAnnotationView(withIdentifier:for:)

    如果要关闭群集,我将对显示的“简单图钉”注释视图重复该过程。

    mapView.register(CustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: CustomAnnotationView.reuseID)
    

    mapView.register(CustomSimplePinAnnotationView.self, forAnnotationViewWithReuseIdentifier: CustomSimplePinAnnotationView.reuseID)
    

    然后简化您的class CustomSimplePinAnnotationView: MKPinAnnotationView { static let reuseID = "CustomSimplePinAnnotationView" override init(annotation: MKAnnotation?, reuseIdentifier: String?) { super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) isDraggable = true canShowCallout = true } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }

    viewFor