Rather than working directly with an iPhone’s camera, you use the UIImagePickerController to manipulate an iPhone’s camera and photo library. Using the UIImagePickerController, you take, or select, a photo, optionally edit the photo, and then dismiss the UIImagePickerController, returning control back to your application.
The UIImagePickerController is different from other view controllers. Rather than developers creating the controller’s view and adding components to the view’s canvas, the UIImage PickerController’s views are already created and are part of the UIKit library. Developers simply determine the controller’s source type and implement a delegate for the controller. The controller creates and manages the views while the delegate responds to the view being dismissed by a user.
The iPod touch, as of this book’s publication, does not have a camera. The iPhone Simulator also lacks a camera. If you attempted to use an iPod touch’s nonexistent camera, you would obtain an exception. Attempting to use the camera on an iPhone Simulator results in a nonresponsive application after it logs a message to the debugger console (Figure 13-15). 2009-02-09 06:50:30.164 CameraProject[216:20b] photos can only be captured on HW To avoid an exception or nonresponsive application, the UIImagePickerController provides the isSourceTypeAvailable: method. + (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType) sourceType This method returns YES if a source type is available and NO if unavailable. Valid source types are UIImagePickerControllerSourceTypePhotoLibrary, for selecting images from the photo library; UIImagePickerControllerSourceTypeCamera, for selecting images from the camera; and UIImagePickerControllerSourceTypeSavedPhotosAlbum, for selecting images from a camera roll, or from the photo library if the device doesn’t have a camera. After ensuring a device has a source type, you set the UIImagePickerController’s sourceType property. This property determines what controls the UIImagePickerController displays. Allowable source types are the same as with the isSourceTypeAvailable: method.
The controller also has an allowsImageEditing property and delegate property. The allowsImageEditing property determines if a user should be allowed to edit an image after taking or selecting the image. The delegate property specifies the class’s UIImagePicker ControllerDelegate.
Figure 13-15 Using a camera on the iPhone Simulator results in a nonresponsive application.
The UIImagePickerControllerDelegate’s protocol has two methods your delegate should implement for the image picker. The imagePickerController:didFinishPickingMediaWithInfo :info: method is called after a user selects an image. This could be selecting an image from a camera roll or photo library, or after taking a photo using the camera. The method’s signature follows.(void)imagePickerController:(UIImagePickerController *) picker didFinishPickingMediaWithInfo: (NSDictionary *) info; If you cancel a photo selected, the imagePickerControllerDidCancel: method is called. The method’s signature follows.(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker The imagePickerController:didFinishPickingMediaWithInfo: info: has three parameters. The first parameter holds a reference to the image picker, the second to the image picked, and the third parameter references an NSDictionary containing editing information. If editing is disabled, the third parameter holds nil. If editing is enabled, the parameter holds the unedited image and the cropped rectangle. For more information on the imagePickerController:didFinish PickingMediaWithInfo:info method, refer to Apple’s online UIImagePickerControllerDelegate Reference.
Using the camera or camera roll requires having an iPhone, a developer’s membership, and a provision for this example application. You can select a photo from a photo album using the iPhone Simulator, however. To accommodate more readers, this task limits itself to the iPhone Simulator’s photo library.
Figure 13-16 The application’s canvas
NOTE If running on the iPhone Simulator, comment the code in viewDidLoad that checks if a camera is available. Be certain to only click the Select Photo button.
Listing 13-17 MyImagePickerDelegate.h #import <Foundation/Foundation.h> @interface MyImagePickerDelegate : NSObject <UINavigationController Delegate, UIImagePickerControllerDelegate> { UIImage * selectedImage; } @property (nonatomic, retain) UIImage * selectedImage; @end Listing 13-18 MyImagePickerDelegate.m #import "MyImagePickerDelegate.h" @implementation MyImagePickerDelegate @synthesize selectedImage; - (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker { [picker.parentViewController dismissModalViewControllerAnimated: YES]; [picker release]; }(void)imagePickerController:(UIImagePickerController *) picker didFinishPickingMediaWithInfo:(NSDictionary *) info { selectedImage = (UIImage*)[info objectForKey:UIImagePickerControllerOriginalImage]; [picker.parentViewController dismissModalViewControllerAnimated: YES]; [picker release]; }(void) dealloc { [selectedImage release]; [super dealloc]; } @end Listing 13-19 CameraProjectViewController.h #import <UIKit/UIKit.h> #import "MyImagePickerDelegate.h" @interface CameraProjectViewController : UIViewController { IBOutlet MyImagePickerDelegate * imgPickerDelegate; IBOutlet UIImageView * theImageView; } @property (nonatomic, retain) MyImagePickerDelegate * imgPickerDelegate; @property (nonatomic, retain) UIImageView * theImageView;
@end Listing 13-20 CameraProjectViewController.m #import "CameraProjectViewController.h" @implementation CameraProjectViewController @synthesize imgPickerDelegate; @synthesize theImageView; - (void) viewDidLoad { [super viewDidLoad]; if(!([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])) { NSLog(@"Camera not supported....quitting application"); UIAlertView * myAlert = [[UIAlertView alloc] initWithTitle:@"Camera Error" message:@"Camera Not Supported. Application will terminate." delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil]; [myAlert show]; [myAlert release]; //warning - terminate is undocumented api [[UIApplication sharedApplication] terminate]; } } - (IBAction) takePicture: (id) sender { UIImagePickerController * pickCont = [[UIImagePickerController alloc] init]; pickCont.delegate = imgPickerDelegate; pickCont.allowsImageEditing = YES; pickCont.sourceType = UIImagePickerControllerSourceTypeCamera; [self presentModalViewController:pickCont animated:YES]; NSLog(@"heynow"); } - (IBAction) selectPicture: (id) sender { UIImagePickerController * pickCont = [[UIImagePickerController alloc] init]; pickCont.delegate = imgPickerDelegate; pickCont.allowsImageEditing = YES; pickCont.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; [self presentModalViewController:pickCont animated:YES]; NSLog(@"heynow"); if(self.imgPickerDelegate.selectedImage != nil) self.theImageView.image = self.imgPickerDelegate.selectedImage; } - (void)dealloc { [theImageView release]; [imgPickerDelegate release]; [super dealloc]; } @end Nothing happens after selecting or taking a photo, unless you click one of the application’s buttons a second time. The photo previously selected is then displayed (Figure 13-17). What is supposed to happen is that the theImageView in CameraProjectViewController should display the newly taken photo. You might think that placing the following lines in the selectPicture would solve the problem, but they do not. if(self.imgPickerDelegate.selectedImage != nil) self.theImageView.image = self.imgPickerDelegate.selectedImage; Notice the ―heynow‖ logging added to the delegate’s methods. Immediately after displaying the image picker, the debugger console logs ―heynow.‖ If the logging does not wait for the image picker to finish, the two lines setting the image don’t wait either, and so the image isn’t set correctly until the next time you push one of the application’s two buttons. CameraProjectController must be changed so it is notified when a picture is taken so it can update its view. There are two ways you might fix the image not displaying. First, you could add a reference to the CameraProjectViewController in MyImagePickerDelegate, but I dislike this solution. Why? Adding a CameraProjectViewController to MyImagePickerDelegate as a property introduces close coupling between the two classes. You can never again reuse MyImagePickerDelegate, unless you reuse CameraProjectViewController. Unacceptable. A better solution, in my humble opinion, is using a notification.
If you have ever used Java listeners, you already know a notification’s basic workings. Cocoa’s notifications are similar to Java’s listeners, only easier and more flexible. Every Cocoa application has a notification center, NSNotificationCenter. Classes in your application can post notifications, NSNotification, to the notification center. Other classes can register with the notification center to listen for notifications. Through notifications, classes can communicate with each other without even knowing about one another’s existence. Although this book doesn’t present notifications with any detail, in the next few steps, you add a notification to the CameraProjectViewController.
Figure 13-17 Running the application in iPhone Simulator and using the provided photo library Refer to Apples Introduction to Notification Programming Topics for more information on using notifications.
notification (Listing 13-21).
Listing 13-21 The didFinishPickingMediaWithInfo modified to post a notification - (void)imagePickerController:(UIImagePickerController *) picker didFinishPickingMediaWithInfo:(NSDictionary *) info { self.selectedImage = (UIImage*)[info objectForKey:UIImagePickerControllerOriginalImage]; [[NSNotificationCenter defaultCenter] postNotificationName:@"Image Picked" object:nil]; [picker.parentViewController dismissModalViewControllerAnimated:YES]; [picker release]; } Listing 13-22 The changeImage method - (void) changeImage { NSLog(@"IMAGE CHANGED"); self.theImageView.image = self.imgPickerDelegate.selectedImage; } Listing 13-23 The viewDidLoad method modified to have CameraViewController observe the notification - (void) viewDidLoad { [super viewDidLoad]; if(!([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])) { NSLog(@"Camera not supported....quitting application"); UIAlertView * myAlert = [[UIAlertView alloc] initWithTitle:@"Camera Error" message:@"Camera Not Supported. Application will terminate." delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil]; [myAlert show]; [myAlert release]; //warning - terminate is undocumented api [[UIApplication sharedApplication] terminate]; } [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(changeImage) name:@"ImagePicked" object:nil]; } - (void) dealloc { [super dealloc]; [theImageView release]; [imgPickerDelegate release]; [ [NSNotificationCenter defaultCenter] removeObserver:self]; } In this task, you created an application that uses the UIImagePickerController to control an iPhone’s camera. You created two buttons, one for taking a photo using the camera and one for selecting an image from the photo library. If you obtained provisioning for the application and installed the provisioning on your iPhone, you could install the application on your iPhone and use the camera (Figure 13-18). But instead, you selected photos from the photo library and ran the application on the iPhone Simulator.
Figure 13-18 Using the camera on an iPhone
You liked the article?
Like: 0
Vote for difficulty
Current difficulty (Avg): Medium
TekSlate is the best online training provider in delivering world-class IT skills to individuals and corporates from all parts of the globe. We are proven experts in accumulating every need of an IT skills upgrade aspirant and have delivered excellent services. We aim to bring you all the essentials to learn and master new technologies in the market with our articles, blogs, and videos. Build your career success with us, enhancing most in-demand skills in the market.