MKAnnotations和核心数据的优化

时间:2012-09-28 09:59:56

标签: iphone ios core-data optimization mapkit

我有一些存储在Core Data中的位置(在本例中为> 3000)。打开地图后,我会获取位置并将它们存储在一个数组中。每次更改mapview区域时,我都会调用一个函数来计算当前visibleMaprect中哪些注释可见,并按像素距离过滤它们。 (我知道会有更复杂的优化,比如四叉树,但我现在不会真正实现它,如果它不是非常必要的话)。 这是我的代码:

//locations is an array of NSManagedObjects     
for (int i =0 ; i < [locations count]; i++)
        {
            // managed object class for faster access, valueforkey takes ages ...
            LocationEntity * thisLocation = [locations objectAtIndex:i];
            CLLocationCoordinate2D coord  = CLLocationCoordinate2DMake( [thisLocation.latitude doubleValue],  [thisLocation.longitude doubleValue]) ;
            // mapRect is mapView.visibleMapRect
            BOOL isOnScreen = MKMapRectContainsPoint(mapRect, MKMapPointForCoordinate(coord));      
            if (isOnScreen)
            {
                CGPoint cgp =  [mapView convertCoordinate:coord toPointToView:mapView];
                // compare the distance to already existing annotations
                for (int idx = 0; idx < [annotations count] && hasEnoughDistance; idx++)    
                {        
                    CGPoint cgp_prev = [mapView convertCoordinate:[[annotations objectAtIndex:idx] coordinate] toPointToView:mapView];
                    if ( getDist(cgp, cgp_prev) < dist )    hasEnoughDistance = FALSE;
                }
            }
            if (hasEnoughDistance)
                // if it's ok, create  the  annotation, add to an array and after the for add all to the map
        }

每次缩放/移动后,地图会冻结几秒钟。 我检查了时间分析器,简单的坐标获取有时是1整秒,有时只有0.1,即使坐标是我的模型中的索引属性...这些类型的线似乎需要很长时间: CGPoint cgp = [mapView convertCoordinate:coord toPointToView:mapView];

任何建议如何在不通过此功能的情况下计算两个注释/坐标之间的像素/点距离?或核心数据的任何优化建议?

谢谢:)

1 个答案:

答案 0 :(得分:0)

好吧,我有点错过了没有让他们离你的解释太近。坐标之间的转换非常慢。您可以缓解它的方法是使用MKMapPointForCoordinate将坐标预先计算到地图点并持久存储它们 - 它们仅取决于坐标。然后,您可以快速计算两个注释的地图点之间的距离,根据您当前的地图缩放级别进行缩放,这将与屏幕上的实际距离密切相关。它应该足够准确并且会更快。

我建议计算平方距离并将其与平方dist进行比较。你会在sqrt()上节省很多。

如果您仍然对getDist()(或getSqDist())感到困惑,您可以选择kd树或使用Accelerate Framework进行计算。当我需要计算许多点之间的距离并且加速非常好时,我已经完成了后者。但细节是另一杯茶。如果您需要任何帮助,请告诉我。

您的坐标被编入索引这一事实只会在您通过坐标实际搜索注释时有所帮助,因此如果您只查看所有这些注释,它将无济于事。

处理来自CoreData的长加载时间的一种方法是尝试使注释尽可能轻量级,因此只存储坐标和地图点。然后,您可以根据需要获取其余注释数据。这可以通过代理模式来完成。

还有一件事。快速枚举可能更快,也是更好的实践,所以

for(LocationEntity* thisLocation in locations)

而不是

for (int i =0 ; i < [locations count]; i++)