1
votes

Goal : Get a screenshot of a map with overlays(MKOverlayView) as well as the annotation.

What I have done :

I have a mapview, overlayview as well as an annotation view present. This is all handled by one controller.

I am using the code provided by Apple to take the screenshot

// Create a graphics context with the target size

// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration

// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext

CGSize imageSize = [[UIScreen mainScreen] bounds].size;

if (NULL != UIGraphicsBeginImageContextWithOptions)
    UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
else
    UIGraphicsBeginImageContext(imageSize);

CGContextRef context = UIGraphicsGetCurrentContext();

// Iterate over every window from back to front
for (UIWindow *window in [[UIApplication sharedApplication] windows]) 
{
    if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen])
    {
        // -renderInContext: renders in the coordinate space of the layer,
        // so we must first apply the layer's geometry to the graphics context
        CGContextSaveGState(context);
        // Center the context around the window's anchor point
        CGContextTranslateCTM(context, [window center].x, [window center].y);
        // Apply the window's transform about the anchor point
        CGContextConcatCTM(context, [window transform]);
        // Offset by the portion of the bounds left of and above the anchor point
        CGContextTranslateCTM(context,
                              -[window bounds].size.width * [[window layer] anchorPoint].x,
                              -[window bounds].size.height * [[window layer] anchorPoint].y);

        // Render the layer hierarchy to the current context
        [[window layer] renderInContext:context];
        //for(self.mapView.overlayView.layer.)
        //[self.mapView.overlayView.layer renderInContext:context];    
        // Restore the context
        CGContextRestoreGState(context);
    }
}

// Retrieve the screenshot image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

The problem is that the above line of code gets the screenshot of only the map view and the annotation view. The overlay view is not present.

Also, to clarify my overlay view(MKOverlayView) is an image. This does not show up in the screenshot. I have not used OpenGL. I can see the annotation view that is the default pin but the screenshot is not able to capture the tiles. I have been working on it for a long time. Any help would be much appreciated! Thanks!

Here is what my controller looks like

->> MYController

  ->> MKMapViewOBject
         ->> MKMapViewOverlayView
         ->> MKMapOverlay
         ->> MKAnnotation
         ->> MKAnnotationView

So am I having a problem with my renderInContext:context ?

More Information :

Following code for tile drawing in my overlay view

    UIGraphicsPushContext(context);
NSData* data = //get data

if(data)
{
    UIImage* img = [[UIImage alloc] initWithData:data];
    [img drawInRect:drawRect blendMode:kCGBlendModeNormal alpha:0.4 ];
    [img release];

}

UIGraphicsPopContext();
1

1 Answers

0
votes

The problem was in the drawMapRect. The drawMapRect is called with different values for MKMapRect when overlaying maps by different threads. Therefore, apple wants your code to be thread safe and able to run with multiple different visible MapRects.

I am working on creating the overlays based on the given MapRect now i.e. the visible portion of it.