Pregunta

I'm interested in printing some MKMapViews that are not part of the view hierarchy, and are created only when the user hits Print.

It seems that the following things are true:

  1. Offscreen MKMapViews do not render at all.
  2. Printing a MKMapView prints it rendered however it currently is.

So it seems that to print my map views, I need to get them into the view hierarchy. Luckily, from experimentation it seems that I can put a bunch of map views in front of each other on the screen and they'll still render.

My main question is how do I know they have rendered? If I just fire off the print command immediately after putting the map views in the view hierarchy, they'll print partially rendered, with missing bits, as shown below. I'd like to wait until they have finished loading, then run the print job. (Even better if they can be loading in the background while the print sheet is on screen, and then I just give the user a progress bar after they hit Print until the maps have finished loading.)

(Below: an image showing what happens if you print a partially loaded map view.)

Printout

My secondary question is: is there a better way to print multiple map views? Getting everything into the view hierarchy is not great — it limits the maximum size I can use, and it means I have a lot of awkward code to juggle subviews.

¿Fue útil?

Solución

You should set a delegate (MKMapViewDelegate) on your map views and implement mapViewDidFinishLoadingMap:, which will be called when the map view has finished loading the necessary tiles.

Otros consejos

I have had a similar issue with rendering MKMapView to an image when the map view is not necessarily visible on the screen. I found the following solution worked for me. I hope this helps someone. Basically, it makes sure the map has a window. in ios6.0, you need to give it a window in order to get it to load the map, then in did finish load, you wait around for a bit before you render to give the tiles a chance to load. in ios 5.0, you don't need to wait for didfinishload, you just ensure the map has a window in the render function and the tiles will be visible.

{
      if ([@"5.9.9" compare:[UIDevice currentDevice].systemVersion options:NSNumericSearch] == NSOrderedAscending) {
          // actualVersion is lower than the requiredVersion 
          self.oldSuperview = nil;
          if (self.map.window == nil) {
        self.oldSuperview = self.map.superview;
              [[[[UIApplication sharedApplication] delegate] window] insertSubview:self.map atIndex:0];
          }
      } else { 
         [self performSelector:@selector(renderMap) withObject:nil afterDelay:0.10];
     }

}

-(void) renderMap {

    //map will only render tiles if it has a window, so we need to add it to
    //the main window if it does not have a window.

    if ([@"5.9.9" compare:[UIDevice currentDevice].systemVersion options:NSNumericSearch] != NSOrderedAscending) {
        if (self.map.window == nil) {
            self.oldSuperview = self.map.superview;
            [[[[UIApplication sharedApplication] delegate] window] addSubview:self.map];
        }
    }


    // Generate the image centred
    UIGraphicsBeginImageContextWithOptions(self.map.bounds.size, NO, 0.0);

    [self.map.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();


    // Save the image here


    if ([@"5.9.9" compare:[UIDevice currentDevice].systemVersion options:NSNumericSearch] != NSOrderedAscending) {

        if (self.oldSuperview) {
            [self.map removeFromSuperview];
            [self.oldSuperview addSubview:self.map];
            self.oldSuperview = nil;
        }

    }

}

}



-(void) cleanMap {
      if (self.map.superview == [[[UIApplication sharedApplication] delegate] window]) {

          if (oldSuperview) { 
              [oldSuperview addSubview:self.map];
              self.oldSuperview = nil;
          }
      }
 }
 -(void) mapViewDidFinishLoadingMap:(MKMapView *)mapView {

if ([@"5.9.9" compare:[UIDevice currentDevice].systemVersion options:NSNumericSearch] == NSOrderedAscending) { 
    if (oldSuperview) {

        [self performSelector:@selector(renderMap) withObject:nil afterDelay:1.10];
        [self performSelector:@selector(cleanMap) withObject:nil afterDelay:1.41];
    } else {
        [self renderMap];
    }
} else {
    [self renderMap];
}

 }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top