iOS Advanced Programming: The Image picker

By
On November 22, 2010

Welcome to the iOS Advance Programming series!

Before you read

Before you read the following tutorials you should evaluate yourself and see if you really know enough about iPhone programming to handle this series. If you are having second thoughts I recommend you read the “How to make an iPhone App” series.

In this series I’m going to talk about some iPhone skills that require a little more experience as a programmer. At the beginning it might look like the difficulty hasn’t increased but as we advance you are going to notice you need more programming skills to understand what we are doing.

I’m going to assume that you can write Objective-C and that you are familiar with the skills taught in the “How to make an iPhone App” series.

The Image Picker

The image picker is a controller that allows you to select an image from a thumbnail list or take it with the camera and then grab that selection and do whatever you want with it.

In this tutorial we are going to grab the picked image or take a new one if the device has a camera and load it to an image view.

Open Xcode and create a View-based Project. You can name it whatever you want mine is going to be ‘imagePickerApp’.

The first thing we are going to do is open the imagePickerAppViewController class header file. Here we need to declare the ImagePickerController and the view that is going to handle the selected image. You need to tell the iPhone that your class is the delegate for the ImagePickerController and NavigationController.

The declaration of the class should look like this:

@interface imagePickerAppViewController : UIViewController {

{

UIImagePickerController *picker;

IBOutlet UIImageView * selectedImage;

}

In the graphical user interface we are going to add a button to call the image picker so we need to add a Click handler, don’t forget to add the getter and setters. Here is the code for the body of the class header:

@property (nonatomic, retain) UIImageView * selectedImage;

- (IBAction) buttonClicked;

@end

Now let’s move to the implementation file.

Synthesize the image:

@synthesize selectedImage;

Picking a source

Let’s add the click handler. This function is going to bring the image picker to let the user select the image he want’s to see.

First we initialize the picker and set the delegate to us, then we ask if the device has a camera. If it does, we bring the camera app, take a picture and use it, else, we bring a list with the images we have in the “Photos” app. This is called “picking a source”, if you don’t check if the source exists Apple may reject your app.

If you do not check if the app has a camera your app will crash.

The method should look like this:

-(IBAction) buttonClicked {

picker = [[UIImagePickerController alloc] init];

picker.delegate = self;

if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])

{

picker.sourceType = UIImagePickerControllerSourceTypeCamera;

} else

{

picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

}

[self presentModalViewController:picker animated:YES];

}

Easy, isn’t it? Lets move on.

Grabing the image

When the user receives an image picker it can do two things: select an image, or cancel. You can handle both actions with two built-in methods: imagePickerControllerDidCancel and imagePickerControllerdidFinishPickingMediaWithInfo. Pretty long names, but very clear.

If the user cancels we just dismiss the picker and release the object:

- (void)imagePickerControllerDidCancel:(UIImagePickerController *) Picker {

[[Picker parentViewController] dismissModalViewControllerAnimated:YES];

[Picker release];

}

But if the user selects an image or takes a photo with the camera we assign it to the “selectedImage” object, one of the attributes of the class and then we release the object:

- (void)imagePickerController:(UIImagePickerController *) Picker

didFinishPickingMediaWithInfo:(NSDictionary *)info {

selectedImage.image = [info objectForKey:UIImagePickerControllerOriginalImage];

[[Picker parentViewController] dismissModalViewControllerAnimated:YES];

[Picker release];

}

Building the GUI

Now open the imagePickerAppViewController.xib file from the resources folder to launch the interface builder.

Drag an image view and a button to the application window.

iPhone Advance Programming | The image Picker | image 1

Then connect the buttonClicked method to the button.

iPhone Advance Programming | The image Picker | image 2

Do the same for the UIImageView (Connect it to selectedImage).

Now save and quit interface builder, and build and run the app.

As the simulator has no camera you won’t be able to test the taking photo feature of your app unless you test it in a real device.

If your photo app has no photos you won’t be able to test the app the right way. To solve this, click the home button and drag some images from any folder to the iPhone simulator.

iPhone Advance Programming | The image Picker | image 3

It will load the image in Safari. Click and hold over the image and select “Save Image”.

iPhone Advance Programming | The image Picker | image 4

Now you can see the image in the photo app.

Build and run our app again. Click on the Select Image button and select an album.

iPhone Advance Programming | The image Picker | image 5

Then select an image.

iPhone Advance Programming | The image Picker | image 6

Now you will see the picker is dismissed and you will see a full screen view of the image.

iPhone Advance Programming | The image Picker | image 7

Conclusion

Now you know how to load images to your iPhone apps.

Stay tuned for my next tutorial.

  • thomas

    Very interesting!
    Hope you can tell us about how to store and retrieve the image later.

  • http://www.adamwalsh.net Adam Walsh

    I followed the tutorial step by step and when I click the “Pick an Image” button nothing shows up on the screen. I put a breakpoint in xcode and it is entering the buttonClicked method, it just doesn’t display anything. Thoughts?

    • http://www.oscarvgg.com OscarVGG

      Maybe you forgot to connect the interface to the corresponding method in Interface Builder, or did it but forgot to save.

  • huygir

    No longer works in iOS4.2 in iPad simulator. This did work in 3.2 simulator. I’ve noticed that the folder structure seems perverted now in that 4.2.1 is not created, only a folder for 4.2 (which was never released in final – only 4.2.1).

    I have not tried to create manually, but that’s my next step…

    Any ideas ?

    • Radim

      try changing line where dismissModalViewController….. like this [self YOURVIEWCOntroller] dismissModalViewController animated:YES];

      something like this…..good luck=)

      • Radim

        edit 1.1
        just came out for this ….iOS 5

        instead this [[Picker parentViewController] dismissModalViewControllerAnimated:YES];

        just use

        [Picker dismissModalViewControllerAnimated:YES];

        works great!=)

        • http://TechyVideoTuts Pavel

          Hey guys,

          Nice tutorial.
          As far as I know, the correct way to dismiss a modal view controller, is:

          [[picker presentingViewController] dismissModalViewControllerAnimated:YES];

          Hope it helps you :)

  • tim lanfair

    so i successfully performed this app, but one question, saving the image,, once you quit the application and try to start the app again, errors happen,, abort about,,, how do you save a photo?

  • aprilShowers

    Great tutorial – works great – just what I needed!

  • kk

    Any suggestion on how we can have advanced feature. I need to deploy the Burst (continuous shooting) for the camera. This will allow user to take multiple pictures with single click in a couple of seconds.

  • Anonymous

    what happened after when image picker is dissmis means which method of parent view gets called?

  • http://flick.cloud8studios.com colin

    Thanks for the example, it helped a lot! However, it doesn’t seem to work with the latest version of Xcode (4.2).

    Here’s what I did to make it work for me (Disclaimer: I’m a newbie):

    1. Make sure to have the correct header file for whatever view controller you are calling the picker from. I don’t think this is mentioned above (perhaps cause it’s too obvious?). This avoids a warning in your .m implementation file where you call picker.delegate = self;

    @interface myFirstViewController : UIViewController

    2. Change the calls to dismiss the picker from

    [[Picker parentViewController] dismissModalViewControllerAnimated:YES];

    to

    [self->picker dismissModalViewControllerAnimated:YES];

    This was necessary for me to get the picker to dismiss and show my app again.

    3. If you are using Auto Reference Counting (ARC), then comment out/delete the release lines:

    //[Picker release];

    • Forrest

      can you elaborate more on the correct header. what should the header be in the .h and .m files

  • John

    First let me say thank you for taking the time to share your knowledge.

    I an a new to x-code but have a good grasp on things after reading several books but always need some help now and again.

    It seems to me in the {else statement after checking if the device has a camera there is no other option but to use the camera?

    I run the app on my phone it takes the picture but does not allow me to choose a photo from my albums. Also when I take the picture there is no code to allow to save the photo.

    It will be greatly appreciated for some help with the above.

    John.

  • Andrew Yakovlev

    please add UIImagePickerControllerDelegate and UINavigationControllerDelegate in the declaration of interface imagePickerAppViewController. It should look like this:

    @interface imagePickerAppViewController : UIViewController {

    UIImagePickerController *picker;

    IBOutlet UIImageView * selectedImage;

    }

  • Uruguay

    Nice tutorial men!

  • Pingback: Why does Facebook Camera need to know your location? | Camera Discount Coupons

  • Pingback: Why does Facebook Camera need to know your location? | Mobile News Plus

  • venkata

    new version presentmodelviewcontroller is not worked

  • Gary

    im pretty newish to this kind of coding but have learnt a fair bit and have unfortunately hit a bump in an app im working on.

    I am trying to create a camera application that will allow the user to take a ‘before’ image, then take an ‘after’ image, I would then like the option for the images to be put together (left and right) and saved as one image.

    So far I have managed to code the app to take a single picture with the code below:

    HEADER:

    #import

    @interface ViewController : UIViewController

    @property (strong, nonatomic) IBOutlet UIImageView *beforeImage;

    - (IBAction)cameraBeforeImage:(UIButton *)sender;

    - (IBAction)libraryBeforeImage:(UIButton *)sender;

    - (IBAction)deleteBeforeImage:(UIButton *)sender;

    @property (strong, nonatomic) IBOutlet UIImageView *afterImage;

    - (IBAction)cameraAfterImage:(UIButton *)sender;

    - (IBAction)libraryAfterImage:(UIButton *)sender;

    - (IBAction)deleteAfterImage:(UIButton *)sender;

    - (IBAction)saveImages:(UIButton *)sender;

    ————————————————————————————————————–

    IMPLEMENTATION:

    #import “ViewController.h”

    @interface ViewController ()

    @end

    @implementation ViewController

    - (void)viewDidLoad
    {
    [super viewDidLoad];
    }

    - (void)didReceiveMemoryWarning
    {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

    - (IBAction)cameraBeforeImage:(UIButton *)sender {

    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {

    UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:@”Oops!”
    message:@”This Device Has No Camera, Please Select An Image From Your Library.”
    delegate:nil
    cancelButtonTitle:@”OK”
    otherButtonTitles: nil];

    [myAlertView show];

    }else{

    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;

    [self presentViewController:picker animated:YES completion:NULL];
    }

    }

    - (IBAction)libraryBeforeImage:(UIButton *)sender {

    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

    [self presentViewController:picker animated:YES completion:NULL];
    }

    - (IBAction)deleteAfterImage:(UIButton *)sender {
    }

    - (IBAction)saveImages:(UIButton *)sender {
    }

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

    UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
    self.beforeImage.image = chosenImage;

    [picker dismissViewControllerAnimated:YES completion:NULL];

    }

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

    }

    - (IBAction)deleteBeforeImage:(UIButton *)sender {
    }
    - (IBAction)cameraAfterImage:(UIButton *)sender {
    }

    - (IBAction)libraryAfterImage:(UIButton *)sender {
    }

    - (IBAction)saveImages:(UIButton *)sender {
    }

    ————————————————————————————————-

    Here is the list of things I need to add, any help on any of them would be very much appreciated!

    Add the same functionality to the ‘After’ buttons as the ‘Before’ but to store the image in the ‘afterImage’ Image view.

    Add functionality to the ‘saveImages’ button to save the two taken images as one image stitched together.

    Thank you all in advance!

  • Hi

    How to let a user choose a image, but not a picture for camera roll?