简体   繁体   English

将集群注释添加到具有几个自定义注释视图的地图视图

[英]Adding cluster annotations to a map view, which has several custom annotation views

I have a map view, which has two types of custom annotation views. 我有一个地图视图,其中有两种类型的自定义注释视图。 I am wondering how to add different types of clusters for these views (depending on the types of annotation views). 我想知道如何为这些视图添加不同类型的群集(取决于批注视图的类型)。 Currently I've tried to do everything as in the sample project from WWDC 2017's session 237 "What's new in MapKit". 目前,我已经尝试做所有事情,就像WWDC 2017的237节“ MapKit的新增功能”中的示例项目一样。 But when I register my cluster view, it does nothing (even not get called). 但是,当我注册集群视图时,它什么也不做(甚至没有被调用)。 I guess, that is because I use custom annotation views and don't register them, but instead, use MKMapViewDelegate method mapView(_:viewFor:) . 我猜这是因为我使用自定义注释视图并且不注册它们,而是使用MKMapViewDelegate方法mapView(_:viewFor:) Here is the code where I register my custom cluster annotation ( ClusterView is a subclass of MKAnnotationView where I define my cluster annotation): 这里是我注册我的自定义集群注释(代码ClusterView是的一个子类MKAnnotationView ,我定义我的集群注解):

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

The code above is defined inside a viewDidLoad() method, but again, it doesn't even get called. 上面的代码在viewDidLoad()方法中定义,但是同样,它甚至没有被调用。 So, I think I should implement one of MKMapViewDelegate methods: mapView(_:clusterAnnotationForMemeberAnnotations:) . 因此,我认为我应该实现MKMapViewDelegate方法之一: mapView(_:clusterAnnotationForMemeberAnnotations:) The problem is, I don't have any experience in adding cluster annotations, so I don't know how to implement it right. 问题是,我没有添加集群注释的经验,所以我不知道如何正确实现它。 I've been looking for some examples on the Internet for several weeks but haven't found anything yet (only about third party libraries). 我已经在互联网上寻找一些示例了好几个星期,但还没有发现任何东西(仅关于第三方库)。 If you know how to implement the above mentioned method, or other way of adding clusters to a mapView that has different types of custom annotation views (without using third party libraries), I would appreciate your help. 如果您知道如何实现上述方法,或将集群添加到具有不同类型的自定义批注视图的mapView其他方法(不使用第三方库),请提供帮助。

Try to register your Annotations with String reuse Identifier: 尝试使用字符串重用标识符注册您的注释:

mapView.register(AnnotationViewMarker.self, forAnnotationViewWithReuseIdentifier: "marker")
mapView.register(AppleClusterAnnotationView.self, forAnnotationViewWithReuseIdentifier: "cluster")

I already had this problem too. 我已经有这个问题了。 In case here is an example that work in my app: 如果这是在我的应用中正常工作的示例:

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

    if let marker = annotation as? WifiAnnotation {
        var view = mapView.dequeueReusableAnnotationView(withIdentifier: "marker") as? AnnotationViewMarker
        if view == nil {
            view = AnnotationViewMarker(annotation: marker, reuseIdentifier: "marker")
        }
        return view

    } else if let cluster = annotation as? MKClusterAnnotation {
        var view = mapView.dequeueReusableAnnotationView(withIdentifier: "cluster") as? AppleClusterAnnotationView
        if view == nil {
            view = AppleClusterAnnotationView(annotation: cluster, reuseIdentifier: "cluster")
        }
        return view

    }

    return nil
}

here an exemple of my MKAnnotationView Class: 这是我的MKAnnotationView类的一个示例:

class AppleClusterAnnotationView: MKAnnotationView {
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
    super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
    displayPriority = .defaultLow
    //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 {
        if let cluster = newValue as? MKClusterAnnotation {
            let renderer = UIGraphicsImageRenderer(size: CGSize(width: 40, height: 40))
            let count = cluster.memberAnnotations.count
            let uniCount = cluster.memberAnnotations.filter { member -> Bool in
                return (member as! WifiAnnotation).wifiType != "Ad"
                }.count
            image = renderer.image { _ in
                // Fill full circle with tricycle color
                UIColor(red: 52/255, green: 131/255, blue: 223/255, alpha: 0.22).setFill()
                UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 40, height: 40)).fill()

                // Fill pie with unicycle color
                UIColor(red: 52/255, green: 131/255, blue: 223/255, alpha: 0.22).setFill()
                let piePath = UIBezierPath()
                piePath.addArc(withCenter: CGPoint(x: 20, y: 20), radius: 20,
                               startAngle: 0, endAngle: (CGFloat.pi * 2.0 * CGFloat(uniCount)) / CGFloat(count),
                               clockwise: true)
                piePath.addLine(to: CGPoint(x: 20, y: 20))
                piePath.close()
                piePath.fill()

                // Fill inner circle with white color
                UIColor.white.setFill()
                UIBezierPath(ovalIn: CGRect(x: 8, y: 8, width: 24, height: 24)).fill()

                // Finally draw count text vertically and horizontally centered
                let attributes = [ NSAttributedStringKey.foregroundColor: UIColor.black,
                                   NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 15)]
                let text = "\(count)"
                let size = text.size(withAttributes: attributes)
                let rect = CGRect(x: 20 - size.width / 2, y: 20 - size.height / 2, width: size.width, height: size.height)
                text.draw(in: rect, withAttributes: attributes)

            }
        }
    }
}}

And finally my MKMarkerAnnotationView. 最后是我的MKMarkerAnnotationView。 With that you are all setup to make it works. 这样,您就可以完成所有设置。 You only have to setup your MKAnnotation. 您只需要设置您的MKAnnotation。

MKMarkerAnnotationView: MKMarkerAnnotationView:

class AnnotationViewMarker: MKMarkerAnnotationView {

override open var annotation: MKAnnotation? {
    willSet {
        if let annotation = newValue as? WifiAnnotation {
            clusteringIdentifier = "WifiAnnotation"

            if annotation.wifiType == "yyy" {
                glyphImage = UIImage(named: "yyy")
                selectedGlyphImage = UIImage(named: "yyy")
                markerTintColor = UIColor("#303030")
                glyphTintColor = .white
                displayPriority = .defaultHigh
                titleVisibility = .visible
                animatesWhenAdded = true


            } else {
                glyphImage = UIImage(named: "xxx")
                selectedGlyphImage = UIImage(named: "xxx")
                markerTintColor = UIColor("#3483DF")
                glyphTintColor = .white
                displayPriority = .required
                titleVisibility = .visible
                animatesWhenAdded = true

                let accessButton = UIButton(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
                accessButton.setImage(self.accessAnnotation, for: .normal) //UIImage(named: "accessAnnotation"), for: .normal)
                rightCalloutAccessoryView = accessButton
            }

            //collisionMode = .circle
        }

    }
}

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM