UIViewController
So I wrote an iPhone application for a client using v2.2.1 of the iPhone SDK. (The client did not want to go OS v3.0 yet.) I needed to give a user the capability of taking and uploading a picture with the built-in camera or uploading a picture from the photo library on the phone. Seems pretty straightforward so far. Yes? I thought so. It turned out to be pretty tricky but the solution was very simple and was staring me in the face. The Problem I had a UIViewController with an UIImageView setup to be used as a container for the selected image. I also had several UIButtons on the page. (One button for calling up the camera.
Another button for calling up the photo library, etc...) So what should have happened is that the Camera or photo library UI would display a Modal View window the user instructing them to either take a picture or select a photo from their library. Once they did that, they would be returned to the main view and whatever photo they took or selected would appear in UIImageView as a preview. However, when I was selecting the photo the "editingInfo" NSDictionary object that was supposed to be returned would be there only about 50% of the time. The other 50% it would be returned empty. I double and triple checked my code and it was all correct. Something was zapping my dictionary object and I couldn't, for the life of me, figure out what it was. The second part to this problem was that the preview image never appeared whenever the user was grabbing their image from the camera. It worked if the photo library was the source but not if it was the camera. Very, very frustrating.
Here is my original code: My .h file - @interface AddPhotoController : UIViewController { IBOutlet UIImageView *imageView; IBOutlet UIButton *snapNewPictureButton; IBOutlet UIButton *selectFromPhotoLibraryButton; }@property (nonatomic, retain) UIImageView *imageView; @property (nonatomic, retain) UIButton *snapNewPictureButton; @property (nonatomic, retain) UIButton * selectFromPhotoLibraryButton;
My .m file - @implementation AddPhotoController @synthesize imageView, snapNewPictureButton, selectFromPhotoLibraryButton;
- (IBAction)getCameraPicture:(id)sender { UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.delegate = self; picker.sourceType = UIImagePickerControllerSourceTypeCamera; picker.allowsImageEditing = YES;
[self presentModalViewController:picker animated:YES]; [picker release]; }
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo { NSLog(@"Image Meta Info.: %@",editingInfo);
UIImage *selectedImage = image; imageView.image = selectedImage; self._havePictureData = YES; [self.useThisPhotoButton setEnabled:YES]; [picker dismissModalViewControllerAnimated:YES]; }- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker dismissModalViewControllerAnimated:YES]; }
Like I said before, it all seems pretty straightforward. However, there were two things wrong with the above code. #1. Deprecated Method The UIImagePickerController method, "“ imagePickerController:didFinishPickingImage:editingInfo:, is deprecated in v3.0 of the iPhone OS. So even though I built the app using SDK v2.2.1, because the app will be running on 3.0 devices, I needed to use the new and improved method, - imagePickerController:didFinishPickingMediaWithInfo:editingInfo, which contains FIVE pieces of really important information:
- UIImagePickerControllerMediaType - Which specifies the type of media that this dictionary contains.
- UIImagePickerControllerOriginalImage - Contains the original non-cropped image.
- UIImagePickerControllerEditedImage - Contains the user-edited cropped image.
- UIImagePickerControllerCropRect - Contains the CGRect that was applied to the original image.
- UIImagePickerControllerMediaURL - If the object is a movie, this object contains the URL to be used by the media player.
I simply accessed the "UIImagePickerControllerEditedImage" object from the dictionary and was off to the races. #2. Dismissing the Modal View This one was really painful as it was so simple to solve. In order for the UIImageView to be updated correctly, you must dismiss the ImagePicker modal window BEFORE you attempt to update your UIImageView.
As a result of this, here is my updated method call: - (void) imagePickerController:(UIImagePickerController *)thePicker didFinishPickingMediaWithInfo:(NSDictionary *)imageInfo { [thePicker dismissModalViewControllerAnimated:YES]; UIImage *img = [imageInfo objectForKey:@"UIImagePickerControllerEditedImage"]; previewImage.image = nil; self.previewImage.image = img;
NSData *imageData = UIImagePNGRepresentation(img); if ([imageData length] > 0) {
[self archivePictureData:imageData]; self._havePictureData = YES;
[self.useThisPhotoButton setEnabled:YES]; }
}
That was it. Hope that was helpful.