处理大量的MKMapView注释

时间:2011-01-23 20:37:08

标签: iphone objective-c mkmapview

我有一个带有大量注释(3000+)的地图视图,当用户缩放到合理的水平时,一切都很好。

虽然当用户缩小并且大量注释进入视图时,由于一次显示大量注释,因此存在大量减速。处理这个问题的最佳方法是什么?

我正在使用的当前解决方案:

- (void)mapView:(MKMapView *)_mapView regionDidChangeAnimated:(BOOL)animated {

    NSArray *annotations = [_mapView annotations];  
    MapAnnotation *annotation = nil; 

    for (int i=0; i<[annotations count]; i++)
    {
        annotation = (MapAnnotation*)[annotations objectAtIndex:i];
        if (_mapView.region.span.latitudeDelta > .010)
        {
            [[_mapView viewForAnnotation:annotation] setHidden:YES];
            warningLabel.hidden = NO;
        }
        else {
            [[_mapView viewForAnnotation:annotation] setHidden:NO];
            warningLabel.hidden = YES;
        }
    }
}

效果很好虽然由于环路的大小很大,但在放大和缩小以及滚动时会导致很多减速。我似乎无法想出一个更好的方法来处理这个问题,有没有办法只循环显示当前正在显示的注释或沿着那些线来减少循环的大小?

3 个答案:

答案 0 :(得分:7)

据我了解您的代码,如果mapView被缩小超过某个指定值,您将隐藏所有注释的视图。

在我看来,更像以下的东西会更好:

- (void)mapView: (MKMapView*)_mapView regionDidChangeAnimated: (BOOL)animated
{
    if (_mapView.region.span.latitudeDelta > .010 && self.mapViewsHidden == NO) {
        for (MapAnnotation* annotation in _mapView.annotations) {
            [[_mapView viewForAnnotation: annotation] setHidden: YES];
        }
        [self.warningLabel setHidden: NO];
        [self setMapViewsHidden: YES];
    }
    else if (_mapView.region.span.latitudeDelta <= .010 && self.mapViewsHidden == YES) {
        for (MapAnnotation* annotation in _mapView.annotations) {
            [[_mapView viewForAnnotation: annotation] setHidden: NO];
        }
        [self.warningLabel setHidden: YES];
        [self setMapViewsHidden: NO];
    }
}

有了上述内容,在大多数情况下,这段代码唯一能做的就是检查。

另一种解决方案是删除不应在地图上显示的注释。就个人而言,我认为这会更好,这样代码就不必为尚未在地图上显示的注释创建视图。

答案 1 :(得分:6)

我会建议一些事情。一,看看方法annotationsInMapRect:。根据文档,它说:

  

此方法提供了一种快速检索地图特定部分中的注释对象的方法。这种方法比自己在注释属性中对对象进行线性搜索要快得多。

两,看看dequeueReusableAnnotationViewWithIdentifier:。再次根据文档说,它说:

  

出于性能原因,通常应该在地图视图中重用MKAnnotationView对象。当注释视图在屏幕外移动时,地图视图会将它们移动到内部管理的重用队列。随着新注释在屏幕上移动,并且提示您的代码提供相应的注释视图,您应始终尝试在创建新视图之前使其出列。 Dequeueing可以在滚动等性能关键操作期间节省时间和内存。

最后,有几点想法。而不是做每一次这些变化的- (void)mapView:(MKMapView *)_mapView regionDidChangeAnimated:(BOOL)animated方法被调用时,如何根据其他一些规则做(如定时器被炒鱿鱼后[确保每到这个被调用一次复位定时器])?另一件需要考虑的事情是:如何将注释分组在一起,彼此超级接近?比方说,你缩小到罗德岛看起来超级小,也许只是十几像素宽,而你在罗得岛州有100个点 - 你应该只显示一个引脚

希望这有帮助!

答案 2 :(得分:2)

我最终使用OCMapView将我的注释分组到群集中。它是免费的,并且很容易实现到现有代码中。

它会在缩小时自动对注释进行分组,当您放大时,它们会按原样显示为非聚集。

我知道这是一个老问题,但对于其他试图做同样事情的人来说,这是一个很好的选择。