完成选择媒体信息与信息返回空值照片。

30

我正在努力捕获使用4.0返回的图像

- (void)imagePickerController:(UIImagePickerController *)picker 
    didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [[picker parentViewController] dismissModalViewControllerAnimated:YES]; 

    // MediaType can be kUTTypeImage or kUTTypeMovie. If it's a movie then you
    // can get the URL to the actual file itself. This example only looks for images.
    //   
    NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
    // NSString* videoUrl = [info objectForKey:UIImagePickerControllerMediaURL];

    // Try getting the edited image first. If it doesn't exist then you get the
    // original image.
    //
    if (CFStringCompare((CFStringRef) mediaType,  kUTTypeImage, 0) == kCFCompareEqualTo) {               
        UIImage* picture = [info objectForKey:UIImagePickerControllerEditedImage];
        if (!picture)
            picture = [info objectForKey:UIImagePickerControllerOriginalImage];             

        // **picture is always nil
            // info dictionary count = 1


    }

}

发生的情况是info字典总是返回单个条目:

{ UIImagePickerControllerMediaType = "public.image";

这很好,但从未有过图像。
我正在使用论坛中的一个很好的示例来做到这一点,我相信调用是正确的,但从未有过图像。
提前致谢!

有人愿意接手吗?这个项目将会获得巨大的声望提升!!! - Rob Bonner
8个回答

53

我知道这是很久之前的事情,但我为此苦苦挣扎了几个小时,并发现了这个站点和iphonedevsdk.com上有许多类似的问题,但从未找到一个可行的答案。

总结一下,如果图片是从相机胶卷/照片库中选择的,则可以正常工作,但如果是使用相机拍摄的新照片,则永远不起作用。好吧,这就是如何使它同时适用于两者:

在您尝试对信息字典进行任何操作之前,您必须先解除并释放UIImagePickerController。要非常清楚:

这样做是不起作用的:

- (void)imagePickerController:(UIImagePickerController *)picker 
                      didFinishPickingMediaWithInfo:(NSDictionary *)info {

          // No good with the edited image (if you allowed editing)
  myUIImageView.image = [info objectForKey:UIImagePickerControllerEditedImage];
          // AND no good with the original image
  myUIImageView.image = [info objectForKey:UIImagePickerControllerOriginalImage];
          // AND no doing some other kind of assignment
  UIImage *myImage = [info objectForKey:UIImagePickerControllerEditedImage];

  [picker dismissModalViewControllerAnimated:YES];
  [picker release];
}

在所有这些情况下,图像将为nil。

然而,通过先释放UIImagePickerController的魔力...

这个方法是可行的:

- (void)imagePickerController:(UIImagePickerController *)picker 
                      didFinishPickingMediaWithInfo:(NSDictionary *)info {

  [picker dismissModalViewControllerAnimated:YES];
  [picker release];

          // Edited image works great (if you allowed editing)
  myUIImageView.image = [info objectForKey:UIImagePickerControllerEditedImage];
          // AND the original image works great
  myUIImageView.image = [info objectForKey:UIImagePickerControllerOriginalImage];
          // AND do whatever you want with it, (NSDictionary *)info is fine now
  UIImage *myImage = [info objectForKey:UIImagePickerControllerEditedImage];
}

非常简单,但就是这样。


13
你是认真的吗?!这就是我的问题所在吗!天哪。*晕倒*。 - Stephen Furlani
我还没有尝试过,但是有几个选项可能是可行的。第一个是复制信息字典 - NSDictionary *infoDictionary = [NSDictionary dictionaryWithDictionary:info] - 然后将选择器设置为nil - picker = nil。不确定这是否有效。另一个几乎肯定会起作用的选项是在Xcode中为图像选择代码创建一个单独的文件,并将该文件设置为不使用ARC,保留此处的解决方案。 - Matthew Frederick
谢谢,我已经解决了,但是方法有些不同。我在设置UIImage后关闭了相机。我不知道这可能是iOS上的一个错误。 - John Paul Manoza
哇,我遇到了类似的问题,这个解决方法很好用。现在我很好奇为什么它有效? - Chan Jing Hong

17

尽管Matthew Frederick的答案最受欢迎并长期以来一直是适当的回应,但自iOS 5.0起,苹果公司提供了dismissViewControllerAnimated:completion:来替换现在已经弃用(自iOS 6.0起)的dismissViewControllerAnimated:

在完成块中执行图像信息字典检索将对所有人都更有意义。

以他上面的示例为例,现在看起来会是这样的:

- (void)    imagePickerController:(UIImagePickerController *)picker 
    didFinishPickingMediaWithInfo:(NSDictionary *)info 
{
    [picker dismissViewControllerAnimated:YES completion:^{
          // Edited image works great (if you allowed editing)
        myUIImageView.image = [info objectForKey:UIImagePickerControllerEditedImage];
          // AND the original image works great
        myUIImageView.image = [info objectForKey:UIImagePickerControllerOriginalImage];
          // AND do whatever you want with it, (NSDictionary *)info is fine now
        UIImage *myImage = [info objectForKey:UIImagePickerControllerEditedImage];
    }];
}

1
你确定是 [picker dismissModalViewControllerAnimated:YES completion: 而不是 [picker dismissViewControllerAnimated:YES completion:^(void) 吗? - James Dunay
2
这对我来说仍然产生了一个nil结果,在iPad模拟器(iOS 6.1)中运行iPhone应用程序。 - Desty
实际上,这似乎是自iOS 5以来iPad模拟器中存在已久的错误 - 即使在真实设备上似乎可以工作。奇怪。因此,唯一的解决方案是使用资产库... - Desty

4

我尝试了上述所有方法,但在iPad 6.0/6.1模拟器上没有成功,然而我发现信息中包含“UIImagePickerControllerReferenceURL”键,这是我的代码:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
  [picker dismissViewControllerAnimated:YES completion:NULL];

  UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];
  if(NULL == image){
      [MyImageLoader loadImageFromAssertByUrl:[info objectForKey:@"UIImagePickerControllerReferenceURL"]
                                   completion:^(UIImage* img){
                                        //img not null here
                                   }];
  }else{
      //image not null here
  }
}

loadImageFromAssertByUrl的代码如下:

+(void) loadImageFromAssertByUrl:(NSURL *)url completion:(void (^)(UIImage*)) completion{
  ALAssetsLibrary *assetLibrary=[[ALAssetsLibrary alloc] init];
  [assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
      ALAssetRepresentation *rep = [asset defaultRepresentation];
      Byte *buffer = (Byte*)malloc(rep.size);
      NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
      NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
      UIImage* img = [UIImage imageWithData:data];
      completion(img);
  } failureBlock:^(NSError *err) {
      NSLog(@"Error: %@",[err localizedDescription]);
  }];
}

谢谢!我简直不敢相信我们需要这样做来解决iPad模拟器中至少一年前就报告的错误,但至少可以绕过它... - Desty

2

有些版本的XCode和Mountain Lion存在已知的bug。请检查控制台是否出现以下信息:

2013-01-17 21:36:34.946 3sure-ios[5341:1803] Named service 'com.apple.PersistentURLTranslator.Gatekeeper' not found. assetsd is down or misconfigured. Things will not work the way you expect them to.

如果出现上述信息,则可能无法正常工作。请在实际的iOS设备上检查您的应用程序。

尽管如此,重新启动模拟器和XCode似乎可以解决该问题。


我没有看到这个错误,但在模拟器上图像为空,在设备上却可以运行。 - Justin Meiners

0

使用

[[UIImagePickerController alloc] init];

而不是

[[UIImagePickerController alloc] initWithNibName:(NSString *) bundle:(NSBundle *)];

0
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{

    [picker dismissViewControllerAnimated:YES completion:NULL];
    //Image picker for nil value 
    UIImage* selectedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    NSLog(@"my Info :: %@", info);

    if(NULL == selectedImage){
      UIImage * selectedImage =  [PhotoViewController loadImageFromAssertByUrl:[info objectForKey:@"UIImagePickerControllerReferenceURL"]
                                     completion:^(UIImage * selectedImage){
                                         //img not null here
                                         NSLog(@"img2 ::: %@", selectedImage);
                                         uploadImg.image = selectedImage;
                                         [self.view addSubview:PermissionView];
                                     }];
    }else{
        //image not null here
        NSLog(@"Up IMG00 :: %@", uploadImg.image);
        NSLog(@"Sel IMG00 :: %@", selectedImage);
        uploadImg.image = [selectedImage retain];
        NSLog(@"Up IMG22 :: %@", uploadImg.image);
        NSLog(@"Sel IMG22 :: %@", selectedImage);

    }
}


+(UIImage *) loadImageFromAssertByUrl:(NSURL *)url completion:(void (^)(UIImage*)) completion{


    __block UIImage* img;

    ALAssetsLibrary *assetLibrary=[[ALAssetsLibrary alloc] init];

    [assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
        ALAssetRepresentation *rep = [asset defaultRepresentation];
        Byte *buffer = (Byte*)malloc(rep.size);
        NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
        NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
        img = [UIImage imageWithData:data];
        completion(img);
        NSLog(@"img ::: %@", img);
    } failureBlock:^(NSError *err) {
        NSLog(@"Error: %@",[err localizedDescription]);
    }];

    return img;
}

1
我在iPad Air和iOS 8上遇到了同样的问题,但是我通过这些代码解决了我的问题。谢谢。 - dobiho

0

我有相同的症状,但在我的情况下,它最终证明我在UIImagePickerController层次结构中有某个类别覆盖了"uuid"或"setUUID"? 我想CoreData需要这些方法,否则它会变得非常非常混乱,而资源库是全部CoreData内容。


-1
需要按照以下步骤进行:
1)创建UIActionSheet
2)选择必要的资源类型-加载资源
3)didFinishPickingMediaWithInfo-从接收到的图像字典中设置图像
    - (IBAction)actionButtonUpload:(id)sender {

             UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self 

cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Camera",@"Photo Library", nil];

         [actionSheet showInView:self.view];

    }

    #pragma mark -- UIActionSheet Delegate
    -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{

        UIImagePickerController *picker = [[UIImagePickerController alloc] init];

        picker.delegate = self;
        picker.allowsEditing = YES;
        UIAlertView *alert;


        switch (buttonIndex) {
            case 0:
                if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {

                    NSLog(@"No camera!");
                    picker.sourceType = UIImagePickerControllerSourceTypeCamera;
                    [self presentViewController:picker animated:YES completion:NULL];


                } else {

                    alert = [[UIAlertView alloc]initWithTitle:@"Alumnikonnect" message:@"Camera is not available, please select a different media" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];

                    [alert show];

                }
                break;
            case 1:

                if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {

                    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
                    [self presentViewController:picker animated:YES completion:NULL];


                } else {

                    alert = [[UIAlertView alloc]initWithTitle:@"Alumnikonnect" message:@"Photolibrary is not available, please select a different media" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];

                    [alert show];

                }

                break;

        }

    }


    #pragma mark - Image picker delegate

    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
    {
          self.imageEventPic.layer.cornerRadius =   self.imageEventPic.frame.size.height /2;
          self.imageEventPic.layer.masksToBounds = YES;
          self.imageEventPic.layer.borderWidth = 0;
          self.imageEventPic.layer.borderWidth = 1.0f;
          self.imageEventPic.layer.borderColor = [UIColor colorWithRed:0.212 green:0.255 blue:0.302 alpha:1.000].CGColor;


        self.labelUploadPic.hidden = YES;

        self.imageEventPic.image =  info[UIImagePickerControllerOriginalImage];

        [self dismissViewControllerAnimated:YES completion:NULL];

    }


    - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
    {
        [self dismissViewControllerAnimated:YES completion:NULL];

    }

    -(UIImage*)imageWithImage:(UIImage*)image
                 scaledToSize:(CGSize)newSize;
    {
        UIGraphicsBeginImageContext( newSize );

        [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

        UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();

        return newImage;

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接