Coding Explorer Blog

Exploring how to code for iOS in Swift and Objective-C

  • Home
  • Apps
  • About
  • Contact

Choosing Images with UIImagePickerController in Swift

Xcode 11.6 Swift 5.2.4

Last updated on August 12, 2020

Choosing Images with UIImagePickerController in Swift

If your Swift iOS app needs to import a picture from the user’s device, you’ve come to the right place today.

Let’s learn how to use UIImagePickerController to let the user select a photo from their device to load into your app.

Setting up the Storyboard

This is going to be a very simple storyboard.  It’s going to be a button, and a UIImageView (to show our loaded image).  So, start up a new “single view application” project, and let’s name it “ImagePickerTutorial”.  Of course set your project’s language to Swift!Storyboard layout for the UIImagePickerController tutorial

Alright, open up your assistant editor and add an outlet to our image UIImageView:

This UIImageView will show the image that was picked.

As well as an action to our button to load theUIImagePickerController:

This button will load the UIImagePickerController.

Loading the UIImagePickerController

First, we’ll need an instance of UIImagePickerController.  Put it at class scope, so we don’t have to allocate an entirely new one each time the button is tapped.  We’ll also need to adopt a protocol to properly use UIImagePickerController, the aptly named UIImagePickerControllerDelegate, so make the top of your class look something like this:

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    @IBOutlet var imageView: UIImageView!
    
    let imagePicker = UIImagePickerController()

That’s the same IBOutlet we created earlier, but I’m used to having IBOutlets above most properties, so I put the imagePicker constant below it.  The UINavigationControllerDelegate is required when setting this as the delegate for the UIImagePickerController.

We need to give it a few options before actually presenting it.  First, we need to set our view controller as the delegate for the UIImagePickerController, to handle a few events.  So, make your viewDidLoad look like this:

override func viewDidLoad() {
    super.viewDidLoad()

    imagePicker.delegate = self
}

You just need to add that last line, just denoting that “self” (the view controller this is written in) is the delegate for the imagePicker.

Next, head over to that loadImageButtonTapped action we made earlier, and we’ll call up the UIImagePickerController there:

@IBAction func loadImageButtonTapped(_ sender: UIButton) {
    imagePicker.allowsEditing = false
    imagePicker.sourceType = .PhotoLibrary
        
    presentViewController(imagePicker, animated: true, completion: nil)
}

We should set whether the imagePicker wants to allow editing, and we definitely need to set the sourceType property.  The sourceType property wants a value of the enum named UIImagePickerController.SourceType, which gives 3 options:

  • UIImagePickerController.SourceType.photoLibrary
  • UIImagePickerController.SourceType.camera
  • UIImagePickerController.SourceType.savedPhotosAlbum

What are the differences between photoLibrary and savedPhotosAlbum?  Basically, photoLibrary gives the user access to any of their photos available on the device, with albums, overall view, and camera roll.  The savedPhotosAlbum is pretty much just that, the images saved locally to your device, but no access to albums or any of the other views

The camera one is rather self explanatory.  It lets you have the camera as the imageSource.  We can cover this aspect later, for now, let’s just stick to the images saved locally to the user’s device.

Now, if you really want, you could run this app, and it will show the image picker as advertised.  However, it of course won’t do anything with the image you selected, since we haven’t actually implemented code to do anything with its response yet.

Read the Image Picked from UIImagePickerController

Remember how we set this as the UIImagePickerController’s delegate?  We probably should do that now, shouldn’t we?  We need to implement the method “imagePickerController:didFinishPickingMediaWithInfo:” which is called exactly when it sounds like it should be, when the user picks something.

// MARK: - UIImagePickerControllerDelegate Methods

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
        imageView.contentMode = .scaleAspectFit
        imageView.image = pickedImage
    }

    dismiss(animated: true, completion: nil)
}

It will send the data back for us to use in that Swift Dictionary named “info”.  We have to unpack it from there with a key asking for what media information we want.  We just want the image, so that is what we ask for.  For reference, the available options of UIImagePickerController.InfoKey are:

    • mediaType
    • originalImage
    • editedImage
    • cropRect
    • mediaURL
    • referenceURL
    • mediaMetadata
    • livePhoto
    • phAsset
    • imageURL

So, if we did allow editing, we could get to that image there.  The “MediaType” one also lets you know if it is an Image or a Movie.  If you’re curious about the rest of these, take a look at Apple’s Documentation.

So, we got out that part of the dictionary and optionally bound its type-casted form as a UIImage into the constant “pickedImage”.

The next line is not strictly-speaking necessary, but without it, the picture will come in and fill as much of the UIImageView as it can, and ignore its normal aspect ratio.  This is actually a property on UIView, which UIImageView inherits from.  The default is UIViewContentMode.ScaleToFill, hence it filling the area as much as it can.  UIViewContentMode.ScaleAspectFit will tell it to fill as much of the screen as it can, while respecting the actual aspect ratio.  Another option is UIViewContentMode.ScaleAspectFill, which also respects the Aspect Ratio, but it fills the entire view, which usually means zooming in such that the whole view is filled, and some of the image is outside of the view.  This one is similar to a way to fit widescreen movies on a 4:3 TV called Pan and Scan.

The next line of course just sets the image of the UIImageView to be the image we just got pack.  This is analogous to setting the text property of a UILabel to the Swift String that you want to show.

Finally, we dismiss the view controller that was presented modally, the UIImagePickerController.  It will dismiss without this in iOS 8, it seems, but Apple encourages dismissing it yourself.

On that note, there is one other method from the UIImagePickerControllerDelegate protocol that we should implement, imagePickerControllerDidCancel.  This one is called when the user taps the “Cancel” button.  You are handed back a reference to the cancelled UIImagePickerController, and inside this method you should again dismiss the UIImagePickerController that you presented.

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
    dismiss(animated: true, completion: nil)
}

Now, you can run your app, use the UIImagePickerController, and have it’s results show up in the UIImageView!  There isn’t any zooming or panning yet, but this was mostly a tutorial for UIImagePickerController than the UIImageView itself.  We’ll cover that another day.

For reference, the entire code for this app is:

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    @IBOutlet var imageView: UIImageView!
    
    let imagePicker = UIImagePickerController()
    
    @IBAction func loadImageButtonTapped(_ sender: UIButton) {
        imagePicker.allowsEditing = false
        imagePicker.sourceType = .photoLibrary
        
        present(imagePicker, animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        imagePicker.delegate = self
    }

    // MARK: - UIImagePickerControllerDelegate Methods
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            imageView.contentMode = .scaleAspectFit
            imageView.image = pickedImage
        }
        
        dismiss(animated: true, completion: nil)
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true, completion: nil)
    }
}

Conclusion

 Screenshots taken from Xcode 6.3.1, code checked against version listed at top of the post.

One thing to note, this post borrowed heavily from Steve Lipton’s post  Swift Swift: Using the UIImagePickerController for a Camera and Photo Library.  It’s a great post, and I hadn’t used UIImagePickerController much before this point, so it was very helpful.  He covers significantly more topics like how to use the camera option, putting this whole thing in a Popover (which you’ll want to do if using this on an iPad), dealing with the situation of the device not having a camera (like the Simulator), and even some Auto Layout.  Definitely check out his blog over at makeapppie.com for other great iOS tutorials in Swift.

The UIImagePickerController makes it easy for your users to select photos from their device, and keeps the user experience consistent with the other apps that also use it, including Apple’s own apps.

I hope you found this article helpful.  If you did, please don’t hesitate to share this post on Twitter or your social media of choice, every share helps.  Of course, if you have any questions, don’t hesitate to contact me on the Contact Page, or on Twitter @CodingExplorer, and I’ll see what I can do.  Thanks!

Sources

  • UIImagePickerController Class Reference — Apple Inc.
  • UIImagePickerControllerDelegate Protocol Reference — Apple Inc.
  • Swift Swift: Using the UIImagePickerController for a Camera and Photo Library — Steve Lipton

Filed Under: Tutorial Tagged With: Swift

Subscribe to the Coding Explorer Newsletter

* indicates required

Follow Us

Facebooktwitterrss

Recent Posts

  • Error Handling in Swift
  • Creating and Modifying a URL in your Swift App
  • Watch Connectivity in Swift — Application Context
  • watchOS Hello World App in Swift
  • API Availability Checking in Swift

Categories

  • Class Reference
  • General
  • Interface Builder
  • My Apps
  • Objective-C
  • Swift
  • Syntax
  • Tutorial
  • Uncategorized

Archives

  • May 2016
  • March 2016
  • February 2016
  • December 2015
  • July 2015
  • June 2015
  • April 2015
  • February 2015
  • January 2015
  • December 2014
  • November 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014
  • June 2014
  • May 2014
  • April 2014
  • March 2014
  • January 2014
  • November 2013
  • September 2013
  • August 2013
  • July 2013
  • Terms Of Use
  • Privacy Policy
  • Affiliate Disclaimer

Subscribe to the Coding Explorer Newsletter

* indicates required

Copyright © 2025 Wayne Media LLC · Powered by Genesis Framework · WordPress