user843337
user843337

Reputation:

Load MKMapView in background and create UIImage from it (iPhone & iPad)

I have a situation whereby I need a way of loading an MKMapView with several overlays. This map view shouldn't be shown onscreen, the only reason I require it to load is in order to create an image from the map for use elsewhere.

I have had a look around online but I haven't had any luck with finding a solution to the problem. Please can someone help me out?

Here is what I've tried so far (with no success)

// Load the map view
Logs_Map_ViewController *mapViewController = [[Map_ViewController alloc] initWithNibName:@"Map_ViewController" bundle:nil];
mapViewController.GPSCoordinatesToPlot = [someDictionary objectForKey:kGPSCoords];

// Take a picture of the map
UIImage *mapImage = [mapViewController convertMapToImage];
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(mapImage)];
NSString *base64String = [imageData base64EncodedString];

NOTE: It's really important that the app waits for the map to fully load (so that the image is created properly).

Upvotes: 4

Views: 3089

Answers (3)

Bigyelow
Bigyelow

Reputation: 51

The method below will always be called as the delegate of mapView,

mapViewDidFinishRenderingMap:fullyRendered:

so, you can get map image from mapView here

- (UIImage *)renderToImage:(MKMapView *)mapView
{
  UIGraphicsBeginImageContext(mapView.bounds.size);
  [mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return image;
}

Upvotes: 0

user1347111
user1347111

Reputation:

This may or may not be helpful but this is what I do in my situation.

I have a tableview for an venue/business with 7 table cells. One of the table cells contains a map with pindrop. When the user views an establishment for the very first time, i run a quick conditional to see if the mapview has been cached (or rather, saved as image). if the image does not exist, i load a fresh mapview into the cell and add a single pindrop annotation. After both the mapview has loaded and the annotation has dropped, i save the view layer to image, then remove the mapview (and release it since we needed to keep the delegate alive) from the cell and replace with the fresh new image. I suggest spawing a background thread to save the image/insert into cell. This way the table view doesn't choke up.

And then finally, the next time the user returns to that same venue/business, the mapview image exists and i load the image.

I know it's important for the map to fully load, otherwise your image saves with gray where the map did not load. if you're dropping a pin drop, you need to make sure your image saving method fires after both the map finished loading (mapViewDidFinishLoadingMap:) and your annotation has dropped (mapView:didAddAnnotationViews:). Only after both have finished should you fire method to save image. i suggest using a delayed selector. I delay it by 1 second.

This same concept can surely be applied to other situations. Bottom line is, as strings42 states, you're going to have to add a visible mapview to your view in order to capture an image.

Upvotes: 1

strings42
strings42

Reputation: 543

You should be able to implement mapViewDidFinishLoadingMap in the MKMapViewDelegate protocol and store your image there, I would think. That should solve the problem of needing to wait until the map is loaded to store the image.

If you're seeing other issues as well, please provide more detail on those, as your question is not clear on the specific issue(s) that you're asking about.

Upvotes: 0

Related Questions