xcode 向 MKMapView 添加多个叠加层

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10924874/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 00:31:19  来源:igfitidea点击:

Adding multiple overlays to MKMapView

objective-ciosxcodemkmapviewmkoverlay

提问by random

I am having some trouble understanding how to add multiple overlays to MKMapView.

我在理解如何向 MKMapView 添加多个叠加层时遇到了一些麻烦。

I have an array routes tracked. The routes tracked are arrays of CLLocations. So I have an array of arrays.

我跟踪了一个数组路由。跟踪的路线是 CLLocations 数组。所以我有一个数组数组。

I am able to take one route and draw it on the map view. However, I need to draw ALL the routes onto the map view.

我可以选择一条路线并将其绘制在地图视图上。但是,我需要将所有路线绘制到地图视图上。

So here is how I go about creating the MKPolyline for 1 route:

下面是我为 1 条路线创建 MKPolyline 的方法:

-(void) loadRoute
{
    //So we grab an array that holds all the locations of one route. 
            NSArray *locations = [[NSArray alloc] initWithArray:[routesArray objectAtIndex:0]];

            // 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) *[locations count]);

            for(int idx = 0; idx < [locations count]; idx++)
            {
                CLLocation *tempLoc = (CLLocation*)[locations objectAtIndex:idx];

                CLLocationDegrees latitude  = tempLoc.coordinate.latitude;
                CLLocationDegrees longitude = tempLoc.coordinate.longitude;

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

                MKMapPoint point = MKMapPointForCoordinate(coordinate);

                // 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;
            }


            self.routeLine = [MKPolyline polylineWithPoints:pointArr count:[locations count]];

//Zoom in to fit route on screen
            _routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y);

            // clear the memory allocated earlier for the points
            free(pointArr);

}

Here is the MapKit delegate call that returns the overlay:

这是返回叠加层的 MapKit 委托调用:

#pragma mark MKMapViewDelegate

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
    MKOverlayView* overlayView = nil;

    if(overlay == self.routeLine)
    {
        //if we have not yet created an overlay view for this overlay, create it now. 
        if(nil == self.routeLineView)
        {
            self.routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine];
            self.routeLineView.fillColor = [UIColor redColor];
            self.routeLineView.strokeColor = [UIColor redColor];
            self.routeLineView.lineWidth = 3;
        }
        overlayView = self.routeLineView;
    }

    return overlayView;
}

So all the code given above works fine. I can't figure out how to load more overlays to show the other routes.

所以上面给出的所有代码都可以正常工作。我不知道如何加载更多叠加层以显示其他路线。

I thought that maybe in loadRoute method, running through all the routes and creating a MKOverlayView for each one. Storing all those MKOverlayView in an array then doing: [self.mapView addOverlays:array];

我认为可能在 loadRoute 方法中,遍历所有路由并为每个路由创建一个 MKOverlayView。将所有这些 MKOverlayView 存储在一个数组中,然后执行: [self.mapView addOverlays:array];

But it doesn't work. The problem is that in the delegate method I somehow need to know which overlay to return.

但它不起作用。问题是在委托方法中,我需要知道要返回哪个叠加层。

So if I could do something along the lines of:

所以,如果我可以做一些类似的事情:

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
    int tag = overlay.tag;
    return (MKOverlayView*)[arrayOfViews objectAtIndex:tag];
}

it would work fine. But unfortunately it doesn't work like that :(

它会正常工作。但不幸的是它不能那样工作:(

Any help would be very much appreciated!

任何帮助将不胜感激!

EDIT:

编辑:

I use this in ViewDidLoad to add the overlay:

我在 ViewDidLoad 中使用它来添加叠加层:

[self loadRoute];

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

        // zoom in on the route. 
        [self zoomInOnRoute];

This is in the header:

这是在标题中:

// the data representing the route points. 
    MKPolyline* _routeLine;

    // the view we create for the line on the map
    MKPolylineView* _routeLineView;

    // the rect that bounds the loaded points
    MKMapRect _routeRect;

采纳答案by random

The routeLineand routeLineViewvariables can only point to one overlay and overlay view at a time so you would theoretically need an array of such variables.

routeLinerouteLineView变量只能指向一个覆盖和叠加视图在一个时间,所以你在理论上需要这样的数组变量。

However, based on the code shown, you don't need to keep references to these in the first place.

但是,根据显示的代码,您不需要首先保留对这些的引用。

I suggest removing the routeLineand routeLineViewvariables.

我建议删除routeLinerouteLineView变量。

Then you just create an overlay object locally and in viewForOverlayreturn a view for the requested overlayparameter.

然后,您只需在本地创建一个覆盖对象,并viewForOverlay返回请求overlay参数的视图。

In the loadRoutemethod, you can loop through the routesArrayand for each route, create a local overlay object, and call addOverlayon it.

在该loadRoute方法中,您可以遍历routesArray每个路由的和 ,创建一个本地覆盖对象,并对其进行调用addOverlay

There's also an easier way to construct a map rect that bounds all the routes so you can set the map's region to show them all.

还有一种更简单的方法来构建一个地图矩形,它限制了所有的路线,这样你就可以设置地图的区域来显示它们。

Example:

例子:

-(void) loadRoute
{
    _routeRect = MKMapRectNull;

    for (int raIndex = 0; raIndex < routesArray.count; raIndex++) 
    {
        //So we grab an array that holds all the locations of one route. 
        NSArray *locations = [[NSArray alloc] initWithArray:
                                 [routesArray objectAtIndex:raIndex]];
        //note we are getting object at raIndex (not 0) above

        //...no change to existing code here...

        //self.routeLine = [MKPolyline polylineWithPoints:pointArr count:[locations count]];
        //replace above line with this...
        MKPolyline *pl = [MKPolyline polylineWithPoints:pointArr count:[locations count]];
        [mapView addOverlay:pl];

        //Zoom in to fit route on screen
        //_routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y);
        //replace above line with this to create a rect around ALL routes...
        if (MKMapRectIsNull(_routeRect))
            _routeRect = pl.boundingMapRect;
        else
            _routeRect = MKMapRectUnion(_routeRect, pl.boundingMapRect);

        // clear the memory allocated earlier for the points
        free(pointArr);
    }    
}

In viewDidLoad, just call loadRouteand don't call addOverlay.

在 中viewDidLoad,只打电话loadRoute,不要打电话addOverlay


The viewForOverlaymethod becomes much simpler:


viewForOverlay方法变得简单多了:

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
    MKPolylineView *pv = [[MKPolylineView alloc] initWithPolyline:overlay];
    pv.fillColor = [UIColor redColor];
    pv.strokeColor = [UIColor redColor];
    pv.lineWidth = 3;
    return pv;
}


By the way, in loadRoute, this line:


顺便说一句,在loadRoute,这一行:

MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) *[locations count]);

should be:

应该:

MKMapPoint* pointArr = malloc(sizeof(MKMapPoint) *[locations count]);

It should use the size of MKMapPoint(not CLLocationCoordinate2D).
They are not the same thing (even though the structs happen to be the same byte size).

它应该使用MKMapPoint(not CLLocationCoordinate2D)的大小。
它们不是一回事(即使结构恰好是相同的字节大小)。