iOS将MKMapView转换为UIImage。永远不要进入街区

时间:2014-05-09 16:16:23

标签: ios objective-c uiimage mkmapview objective-c-blocks

基于这个答案:

Snapshot of MKMapView

我尝试将地图转换为图片,但应用程序永远不会进入快照程序块。

为什么?

//Get location an then get a Picture of the Map.
CLLocation *userLoc = self.map.userLocation.location; //self.map is a MKMapView;
CLLocationCoordinate2D punto = userLoc.coordinate;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(punto, 500, 500);
[self.map setRegion:(region)];
[self.map setShowsUserLocation:YES];
//Place a Pin in actual location.
MKPointAnnotation *pin = [[MKPointAnnotation alloc]init];
pin.coordinate = punto;
pin.title = @"Localización";
[self.map addAnnotation:pin];

//Convert map to picture.
MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
options.region = self.map.region;
options.scale = [UIScreen mainScreen].scale;
options.size = self.map.frame.size;

MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
[snapshotter startWithQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) completionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
    NSLog(@"Entering the block."); //Never prints!
    // get the image associated with the snapshot
    UIImage *image = snapshot.image;
    NSLog(@"imagen %@",image); //Niether do this!
    // Get the size of the final image
    CGRect finalImageRect = CGRectMake(0, 0, image.size.width, image.size.height);
    // Get a standard annotation view pin. Clearly, Apple assumes that we'll only want to draw standard annotation pins!
    MKAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:@""];
    UIImage *pinImage = pin.image;
    // ok, let's start to create our final image
    UIGraphicsBeginImageContextWithOptions(image.size, YES, image.scale);
    // first, draw the image from the snapshotter
    [image drawAtPoint:CGPointMake(0, 0)];
    // now, let's iterate through the annotations and draw them, too
    for (id<MKAnnotation>annotation in self.map.annotations)
    {
        CGPoint point = [snapshot pointForCoordinate:annotation.coordinate];
        if (CGRectContainsPoint(finalImageRect, point)) // this is too conservative, but you get the idea
        {
            CGPoint pinCenterOffset = pin.centerOffset;
            point.x -= pin.bounds.size.width / 2.0;
            point.y -= pin.bounds.size.height / 2.0;
            point.x += pinCenterOffset.x;
            point.y += pinCenterOffset.y;
            [pinImage drawAtPoint:point];
        }
    }
    // grab the final image
    UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
    NSLog(@"Picture inside the block %@",finalImage);  //Never prints.
    UIGraphicsEndImageContext();
    // and save it
    NSData *data = UIImagePNGRepresentation(finalImage);
    [data writeToFile:@"Picture.jpg" atomically:YES];
    if (error) {
        NSLog(@"Error"); //This is not printed.
    }else{
        NSLog(@"Success!"); //Neither do this.
        self.fotoParaEnviar = finalImage;
    }
}];
NSLog(@"Picture outside the block %@",self.fotoParaEnviar); //This is allway NULL

看起来一切都被实例化了。

那么为什么块永远不会被执行?

3 个答案:

答案 0 :(得分:1)

如果你已经在显示地图,那么将它保存到图像中就没有必要了,Snapshot of MKMapView in iOS7几乎可以正确地得到它,我不明白他们为什么会得到黑色图像,但是我没有传递0.0渲染比例,但1.0或2.0(视网膜),也许他们的代码不在主线程上,因为它应该是图形。

无论如何,我刚刚在7.1上尝试了这个,并使用用户蓝点和注释引脚获得了正确的图像:

[ObCommons createJPEGfromView:self.map withSize:self.map.bounds.size toPath:[ObCommons getPathInDocuments:@"test.jpg"]];
+(UIImage*) createImageFromView:(UIView*)newt withSize:(CGSize)rensize {
    UIGraphicsBeginImageContextWithOptions(rensize, NO, 2.0);   // 1.0 or 2.0 for retina (get it from UIScreen)
    [newt.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();

    return image;
}

+(UIImage*) createJPEGfromView:(UIView*)newt withSize:(CGSize)rensize toPath:  (NSString*)filePath quality:(float)quality{
    UIImage *ximage = [ObCommons createImageFromView:newt withSize:rensize];    
    NSData *imageData = UIImageJPEGRepresentation(ximage, quality);

    if (filePath!=nil) {
        [imageData writeToFile:filePath atomically:YES];
    }

    return ximage;
}

+(CGFloat)retinaFactor {
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] > 1) {
        return [[UIScreen mainScreen]scale];
    } else {
        return 1.0f;
    }
}

为了更具可读性,以下是相关方法的要点:https://gist.github.com/quentar/d92e95728ce0d950db65

答案 1 :(得分:0)

如果你改变这个怎么办:

[snapshotter startWithQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

对此:

[snapshotter startWithQueue:dispatch_get_main_queue()

NSLog(@"Picture inside the block %@",self.fotoParaEnviar);将始终为NULL,snapshotterasync,当您到达NSLog时,上面的代码仍会执行其阻止

或者你也可以试试这个instad:

[snapshotter startWithCompletionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
    UIImage *image = snapshot.image;
    // and so on
}];

答案 2 :(得分:0)

我将使用以下解决方案关闭此问题:

FIRST 让MKMapView在View中加载 completly ,然后输入块将其转换为UIImage。

谢谢大家的帮助。