如何优化绘制地图叠加的代码

时间:2013-08-19 10:01:32

标签: iphone ios objective-c mkmapview mkpolyline

我根据iPhone上存储在SQLite中的坐标在MKMapView上绘制路径 但是现在我在数据库中存储了14000个坐标(只是lat / lng),现在当我想显示覆盖路径时,我的应用程序崩溃了。
我的问题是有没有办法优化这个代码更快? 这是在视图中加载:

// ar is NSMutableArray and it is populate from database for a few seconds but code bellow cost me app crash
    for(Path* p in ar)
        {
            self.routeLine = nil;
            self.routeLineView = nil;

            // while we create the route points, we will also be calculating the bounding box of our route
            // so we can easily zoom in on it.
            MKMapPoint northEastPoint;
            MKMapPoint southWestPoint;

            // create a c array of points.
            MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) * ar.count);

            for(int idx = 0; idx < ar.count; idx++)
            {
                Path *m_p = [ar objectAtIndex:idx];

                CLLocationDegrees latitude  = m_p.Latitude;
                CLLocationDegrees longitude = m_p.Longitude;

                // create our coordinate and add it to the correct spot in the array
                CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);


                MKMapPoint point = MKMapPointForCoordinate(coordinate);

                // adjust the bounding box
                // if it is the first point, just use them, since we have nothing to compare to yet.
                if (idx == 0) {
                    northEastPoint = point;
                    southWestPoint = point;
                }
                else
                {
                    if (point.x > northEastPoint.x)
                        northEastPoint.x = point.x;
                    if(point.y > northEastPoint.y)
                        northEastPoint.y = point.y;
                    if (point.x < southWestPoint.x)
                        southWestPoint.x = point.x;
                    if (point.y < southWestPoint.y)
                        southWestPoint.y = point.y;
                }

                pointArr[idx] = point;
            }

            // create the polyline based on the array of points.
            self.routeLine = [MKPolyline polylineWithPoints:pointArr count:ar.count];

            _routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y);
            // clear the memory allocated earlier for the points
            free(pointArr);


            [self.mapView removeOverlays: self.mapView.overlays];
            // add the overlay to the map
            if (nil != self.routeLine) {
                [self.mapView addOverlay:self.routeLine];
            }



更新

viewDidLoad中:

...
[self performSelectorInBackground:@selector(drawPathInBackground) withObject:nil];
...
-(void)drawPathInBackground{
for(int idx = 0; idx < ar.count; idx++)
    { ... }
[self.mapView performSelector:@selector(addOverlay:) onThread:[NSThread mainThread] withObject:self.routeLine waitUntilDone:YES];
}

我确实喜欢这样,UI不会冻结 唯一剩下的就是如何在每个X点上绘制 MKPolyLine

4 个答案:

答案 0 :(得分:4)

三种方法:

  1. 不显示每个点,而是将附近的点组合成一个点。保存取决于您的数据和显示所有数据的必要性。
  2. 如果可能的话,在后台线程中加载数据并在主线程上以多个批次显示。用户几乎可以看到数据如何在一段时间后加载。
  3. 懒洋洋地加载和显示数据。表示:仅显示屏幕上可见的那些点

答案 1 :(得分:4)

从数据库中提取并在后台线程中处理。

然后使用Douglas–Peucker algorithm

减少路径中的坐标数

Douglas–Peucker algorithm

并缓存结果。

答案 2 :(得分:1)

如果您有坐标数组,请使用此代码

这里的路线是坐标数组。

NSLog(@"count %d",[routes count]);
MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) * [routes count]);

for(int idx = 0; idx < [routes count]; idx++)
{
    CLLocation* location = [routes objectAtIndex:idx];
    CLLocationCoordinate2D workingCoordinate;       
    workingCoordinate.latitude=location.coordinate.latitude;
    workingCoordinate.longitude=location.coordinate.longitude;  
    NSLog(@"loop = %f,%f",workingCoordinate.latitude, workingCoordinate.longitude);
    MKMapPoint point = MKMapPointForCoordinate(workingCoordinate);
    pointArr[idx] = point;      
}   
// create the polyline based on the array of points. 
self.routeLine = [MKPolyline polylineWithPoints:pointArr count:[routes count]];
[mapView addOverlay:self.routeLine];
free(pointArr);

希望这有帮助。

答案 3 :(得分:0)

谷歌有一个可以将位置编码为字符串的算法。 根据您的情况,14000坐标将编码为一个近14000长度的字符串。 然后将String放入sqlite。 它将加快从DB获取数据的速度