Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: Notification when MKMapView is loaded and annotations/overlays are added?

I am aware of the delegate methods used to let me know when the map has loaded and annotations and overlays have been added. (mapViewDidFinishLoadingMap: mapView:didAddAnnotationViews: mapView:didAddOverlayViews:)

I am wanting to create a UIImage from my MKMapView once everything has loaded. Currently I am creating my UIImage once mapView:didAddOverlayViews: is called, but this is not always reliable, because sometimes the overlay take longer to be added, sometimes mapViewDidFinishLoadingMap: is called more than once or it takes a long time to load. Sometimes it is NOT called because tiles are cached. So, it is very hard to know exactly when everything has loaded. I have tried using a timer but that doesn't make it reliable either.

My question is, how can I know when everything has completely loaded, including all map tiles, all annotations and all overlays?

like image 213
Nic Hubbard Avatar asked Dec 07 '11 18:12

Nic Hubbard


4 Answers

It's an old question, but if you're using iOS 7 just use the mapView mapViewDidFinishRenderingMap delegate.

- (void)mapViewDidFinishRenderingMap:(MKMapView *)mapView fullyRendered:(BOOL)fullyRendered
{
    // Image creation code here

}
like image 98
Peter Todd Avatar answered Nov 09 '22 22:11

Peter Todd


The following code works on iOS 8.4 in Swift 1.2

func mapViewDidFinishRenderingMap(mapView: MKMapView!, fullyRendered: Bool) {
    // Your code on rednering completion
}
like image 5
Luke Pearce Avatar answered Nov 09 '22 23:11

Luke Pearce


Well, you could set three flags in your delegate:

- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView
{
    didFinishLoadingMap = YES;
    [self createImage];
}

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
{
    didFinishAddingAnnotationViews = YES;
    [self createImage];
}

- (void)mapView:(MKMapView *)mapView didAddOverlayViews:(NSArray *)overlayViews

{
    didFinishAddingOverlayViews = YES;
    [self createImage];
}

...and then

- (void)createImage
{
    if (didFinishLoadingMap && didFinishLoadingAnnotationViews && didFinishAddingOverlayViews) {
        // Create the image
    }
}

...and then set all three flags back to NO in your mapViewWillStartLoadingMap: method. This might create an image slightly more often than necessary, in the scenario where map tiles are cached but both new overlays and new annotations scroll onto the screen – if you wanted to guard against that, you could use a UIPanGestureRecognizer to detect when the user pans or pinches the map, and reset those two flags to NO accordingly.

like image 1
Scott Forbes Avatar answered Nov 09 '22 21:11

Scott Forbes


The problem with mapViewDidFinishRenderingMap is that is only includes the loading of the map tiles themselves, not the tiles plus the annotations. For this, you can use didAddAnnotationViews. To be safe, I would recommend observing both, and using which ever returns later.

like image 1
Ben Packard Avatar answered Nov 09 '22 23:11

Ben Packard