Swift 2 MapKit Annotations - 如何对注释进行分组?

Posted

技术标签:

【中文标题】Swift 2 MapKit Annotations - 如何对注释进行分组?【英文标题】:Swift 2 MapKit Annotations - How to group annotations? 【发布时间】:2016-02-13 21:14:24 【问题描述】:

我的地图中有近 8000 个注释,我想根据用户在应用中的缩放比例对它们进行分组。

所有的经纬度都已经作为 Double 进入 CoreData。

如果我在同一点有两个不同的注释图像,我想展示两组,一组是十字架,一组是心脏。

当用户单击注释并且此注释是分组注释时,我想向用户显示此位置有多少注释,“强制”用户放大以单独查看注释。

下面是我的应用程序的图片和当前的注释。

谢谢!

【问题讨论】:

【参考方案1】:

我已经拿到了。

var zoomLevel = Double()
var iphoneScaleFactorLatitude = Double()
var iphoneScaleFactorLongitude = Double()
var CanUpdateMap: Bool = false

static func getLatitudeLongitudeLimitsFromMap(mapView: MKMapView) -> [String: Double] 
    var coord = [String: Double]()

    let MinLat: Double = mapView.region.center.latitude - (mapView.region.span.latitudeDelta / 2)
    let MaxLat: Double = mapView.region.center.latitude + (mapView.region.span.latitudeDelta / 2)
    let MinLon: Double = mapView.region.center.longitude - (mapView.region.span.longitudeDelta / 2)
    let MaxLon: Double = mapView.region.center.longitude + (mapView.region.span.longitudeDelta / 2)

    coord["MinLat"] = MinLat
    coord["MaxLat"] = MaxLat
    coord["MinLon"] = MinLon
    coord["MaxLon"] = MaxLon

    return coord


func LoadMap(mapView: MKMapView) 
    // Get the limits after move or resize the map
    let coord: [String: Double] = getLatitudeLongitudeLimitsFromMap(mapView)
    let MinLat: Double = coord["MinLat"]! as Double
    let MaxLat: Double = coord["MaxLat"]! as Double
    let MinLon: Double = coord["MinLon"]! as Double
    let MaxLon: Double = coord["MaxLon"]! as Double
    var arrAnnotations = [MKAnnotation]()

    let FilterMinLat = arrDicListPinsWithLatitudeLongitude.filter(
        if let item = $0["Latitude"] as? Double 
            return item > MinLat
         else 
            return false
        
    )
    let FilterMaxLat = FilterMinLat.filter(
        if let item = $0["Latitude"] as? Double 
            return item < MaxLat
         else 
            return false
        
    )
    let FilterMinLon = FilterMaxLat.filter(
        if let item = $0["Longitude"] as? Double 
            return item > MinLon
         else 
            return false
        
    )
    let FilterMaxLon = FilterMinLon.filter(
        if let item = $0["Longitude"] as? Double 
            return item < MaxLon
         else 
            return false
        
    )

    for Item in FilterMaxLon 
        let dic:[String:AnyObject] = Item
        var Name = String()
        var Address = String()
        var IconPNG = String()

        if let Latitude = dic["Latitude"] as? Double 
            if let Longitude = dic["Longitude"] as? Double 

                    if let item = dic["Name"] 
                        Name = item as! String
                    
                    if let item = dic["Address"] 
                        Address = item as! String
                    

                    if let item = dic["TypeID"] as? Int 
                        if item == 11 
                            IconPNG = "icon-cross.png"
                         else 
                            IconPNG = "icon-heart.png"
                        
                    
                    arrAnnotations.append(CreateAnnotation(Address, Title: Name, Latitude: Latitude, Longitude: Longitude, IconPNG: IconPNG))
                
            
        
    

    // Show in the map only the annotations from that specific region
    iphoneScaleFactorLatitude = mapView.region.center.latitude
    iphoneScaleFactorLongitude = mapView.region.center.longitude

    if zoomLevel != mapView.region.span.longitudeDelta 
        filterAnnotations(arrAnnotations)

        zoomLevel = mapView.region.span.longitudeDelta

        CanUpdateMap = true
    


func filterAnnotations(arrAnnotations: [MKAnnotation]) 
    let latDelta: Double = 0.04 / iphoneScaleFactorLatitude
    let lonDelta: Double = 0.04 / iphoneScaleFactorLongitude
    var shopsToShow = [AnyObject]()
    var arrAnnotationsNew = [MKAnnotation]()

    for var i = 0; i < arrAnnotations.count; i++ 
        let checkingLocation: MKAnnotation = arrAnnotations[i]
        let latitude: Double = checkingLocation.coordinate.latitude
        let longitude: Double = checkingLocation.coordinate.longitude
        var found: Bool = false

        for tempPlacemark: MKAnnotation in shopsToShow as! [MKAnnotation] 
            if fabs(tempPlacemark.coordinate.latitude - latitude) < fabs(latDelta) && fabs(tempPlacemark.coordinate.longitude - longitude) < fabs(lonDelta) 
                found = true
            
        

        if !found 
            shopsToShow.append(checkingLocation)
            arrAnnotationsNew.append(checkingLocation)
        
    

    // Clean the map
    for item: MKAnnotation in self.mapRedes.annotations 
        myMap.removeAnnotation(item)
    

    // Add new annotations to the map
    for item: MKAnnotation in arrAnnotationsNew 
        myMap.addAnnotation(item)
    


func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) 
    // This validation should be added, because it will find all the annotations before the map resize
    if CanUpdateMap == true 
        LoadMap(mapView)
    

【讨论】:

【参考方案2】:

只是对我的代码的更正:

//....

func LoadMap(mapView: MKMapView) 
    //....

    // Show in the map only the annotations from that specific region
    iphoneScaleFactorLatitude = Double(mapView.bounds.size.width / 30) // 30 = width of the annotation
    iphoneScaleFactorLongitude = Double(mapView.bounds.size.height / 30) // 30 = height of the annotation

    //....


func filterAnnotations(mapView: MKMapView, arrAnnotations: [MKAnnotation]) 
    let latDelta: Double = mapView.region.span.longitudeDelta / iphoneScaleFactorLatitude
    let lonDelta: Double = mapView.region.span.longitudeDelta / iphoneScaleFactorLongitude

    //....


//....

【讨论】:

以上是关于Swift 2 MapKit Annotations - 如何对注释进行分组?的主要内容,如果未能解决你的问题,请参考以下文章

Swift:SwiftUI中MapKit的使用体验

如何使用 Mapkit (Swift) 去用户位置

如何在 Swift 中使用 MapKit 在两个位置之间绘制路线?

UItableview行未在swift4中显示mapkit

如何以编程方式在 Mapkit 中选择特定注释 - Swift

在 Swift 游乐场中使用 MapKit 显示地图以快速查看?