2

I am trying to plot multiple points on MKMapView. Between two straight points, it is easy -- I just find the middle coordinates and use them:

// Center
CLLocationCoordinate2D center;
center.latitude = self.midLatitude;
center.longitude = self.midLongitude;
myRegion.center = center;

But what if I have Los Angeles, Washington DC, and Seattle on the map. I have my own code which calculates the center based on the first and the last coordinates in the array. In the above case, I only see LA and Seattle.

Is there another way to determine the center between three points?

Thank you!

EDIT:

New code with MKMapRect added:

-(void) addAnnotation {

MKMapRect showMapRect = MKMapRectNull;
CLLocationCoordinate2D mapLocation;
IGAMapAnnotation *mapAnnotation;

// Calculate how many points are included in the plan
NSInteger numberOfPoints = [coordinatesTempArray count];

MKMapPoint annotationMapPoint;
MKMapRect annotationMapRect;

if (numberOfPoints > 0) {
    // Trying to add coordinates from the array of coordinates
    for (NSInteger i=0; i < ([coordinatesTempArray count]); i++) {

        ... // Code that adds annotations

        // Adding the annotation to the array that will be added to the map
        [mapLocations addObject:mapAnnotation];

        // Adding Annotation coordinates to MKMapRect so that they all be visible in the view
        annotationMapPoint = MKMapPointForCoordinate(mapLocation);
        annotationMapRect = MKMapRectMake(annotationMapPoint.x, annotationMapPoint.y, 0, 0);

        showMapRect = MKMapRectUnion(showMapRect, annotationMapRect);
        }       
    }

    // Showing all annotations at a time
    self.mapView.visibleMapRect = showMapRect;

    // Now I am trying to zoom out a bit since the extreme annotation are right at the border of the mapview. THIS DOES NOT WORK.

    MKCoordinateRegion region;
   region = MKCoordinateRegionForMapRect(annotationMapRect);

    MKCoordinateSpan span;
    span.latitudeDelta = 0.09;
    span.longitudeDelta = 0.09;
    region.span = span;
    region = [self.mapView regionThatFits:region];
    [self.mapView setRegion:region animated:YES];


    // Showing all annotations at a time
    self.mapView.visibleMapRect = showMapRect;


    // Adding annotations to the map
    [self.mapView addAnnotations:mapLocations];

    }
 }
Igor Tupitsyn
  • 1,193
  • 3
  • 18
  • 45
  • Are you just trying to set the map's region to show multiple annotations (see [this](http://stackoverflow.com/questions/22127157/mkpinannotationview-color-is-not-working)) or do you really need the center coordinate for some other reason? If you really need the center, you can get an _approximate_ value by creating an MKPolygon (but not adding it to the map) with the coordinates and looking at its `coordinate` property. –  Aug 11 '14 at 02:55
  • Hello, Anna. Thank you so much for your help, which is brilliant as always (please respond to the original question so that I could add you some points). I did try to set the map's region to show all multiple annotations at a time. Used your link and fixed the issue (please see the edit in my original post). I still have a couple of issues. First, I tried to zoom out a bit, since right now my extreme annotations are right at the edge of the map. Adding region as I show in my code does not solve this issue, although I do not see why. – Igor Tupitsyn Aug 12 '14 at 00:26
  • Second issue, although it is a different topic, but you may know a quick answer. I am trying to implement this: `-(void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error` to show an alert view when there is no internet. Instead, the alert message is showing almost every time I open the map, especially when the map region is big (say the whole America). Is it because it requires time to download the map and the alert view simply shoots without waiting for it? If so, what would be the best way to fix the issue? Thank you. You are the best MKMapView expert! – Igor Tupitsyn Aug 12 '14 at 00:29
  • Problem 1 is solved: `[self.mapView setVisibleMapRect:showMapRect edgePadding:UIEdgeInsetsMake(30, 30, 30, 30) animated:YES];` Still continue to receive error notes even when Internet is available. Thank you! – Igor Tupitsyn Aug 12 '14 at 01:14

1 Answers1

1

In the edited code, trying to "zoom out a bit more" than the calculated MKMapRect doesn't work because:

  1. When calling MKCoordinateRegionForMapRect, it is passing annotationMapRect (the rect for a single annotation) instead of showMapRect (the rect for all the annotations).
  2. The span deltas are set to a fixed value instead of taking the span from showMapRect and expanding it a bit (my multiplying it by say 1.1).
  3. After calling setRegion with the "zoomed out region", code again calls setVisibileMapRect with the original showMapRect which undoes all the work with the zoomed out region.

You could zoom out a bit using setRegion after fixing the above but the simpler way as you already found out is to use setVisibleMapRect:edgePadding:animated: instead of just setVisibleMapRect:.


Regarding the problem with mapViewDidFailLoadingMap:

It's hard to say why the map is failing to load in your specific case.

But whatever the reason(s) might be, if you must let the user know that the map failed to load, my suggestion would be to use a UILabel instead of a UIAlertView.

Rather than make the user tap OK every time the map view has a problem loading, show/hide the label when the map view fails/finishes loading.

This way, the user is "alerted" but they aren't annoyed having to constantly tap OK.

This might give the user a more pleasing experience.

Make the label a subview of the same view that the map view is a subview of. That is, make them siblings. Don't make the label a subview of the map view. Set the label initially to "hidden" or with alpha set to 0 so you could animate the label show/hide in the delegate methods. You can put the label in front of the map view (if there's no room on the screen) but not a subview of the map view.

Example:

//initialize label alpha to 0 in viewDidLoad...
mapLoadFailedLabel.alpha = 0;

-(void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error
{
    [UIView animateWithDuration:0.5 animations:^{
        mapLoadFailedLabel.alpha = 1.0;
    }];
}

-(void)mapViewDidFinishLoadingMap:(MKMapView *)mapView
{
    [UIView animateWithDuration:0.5 animations:^{
        mapLoadFailedLabel.alpha = 0.0;
    }];
}
  • Thank you, Anna. It does look much better as the user does not have to press the alert OK button all the time. It is still weird to see that the whole map gets loaded but there is a sign saying "Problems downloading the map" :-) As I said, interestingly enough, it does not happen when the region is relatively small. Oh, boy... :-) – Igor Tupitsyn Aug 12 '14 at 23:15
  • You might be able to check the `error` parameter and tell whether it is a internet-related failure or not. If it's not internet-related, leave the label hidden. See http://stackoverflow.com/questions/1857958/mapviewdidfailloadingmap-delegate-method-gets-called-with-error-0 for an example. –  Aug 13 '14 at 01:32
  • Thank you. Yes, I have checked the error: `Error Domain=GEOErrorDomain Code=-204 "The operation couldn’t be completed.` Looks like a lot of people have the problem. Did the following remedy: `if (!error.code == -204) {` and the code showing the label. Cheers! – Igor Tupitsyn Aug 13 '14 at 01:45