49

I am trying hard to understand how this works, but it's pretty hard for me. =) I have 1 view, there is one button and one small ImageView area for preview. The button triggers imagepickercontroller, and the UIView will display picked image. There is no error but the image doesn't show in the UIImageView area.

var imagePicker = UIImagePickerController()
@IBOutlet var imagePreview : UIImageView

@IBAction func AddImageButton(sender : AnyObject) {
    imagePicker.modalPresentationStyle = UIModalPresentationStyle.CurrentContext
    imagePicker.delegate = self
    self.presentModalViewController(imagePicker, animated: true)
    
}
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
    var tempImage:UIImage = UIImage(named: UIImagePickerControllerOriginalImage)
    imagePreview.image  = tempImage
    
    self.dismissModalViewControllerAnimated(true)
    
}

func imagePickerControllerDidCancel(picker: UIImagePickerController!) {

    self.dismissModalViewControllerAnimated(true)
}
HangarRash
  • 7,314
  • 5
  • 5
  • 32
user3806731
  • 889
  • 2
  • 8
  • 14

6 Answers6

41

You're grabbing a UIImage named UIImagePickerControllerOriginalImage and there exists no such image. You're meant to grab the UIImage with the key UIImagePickerControllerOriginalImage from the editingInfo dictionary:

let tempImage = editingInfo[UIImagePickerControllerOriginalImage] as! UIImage
DoruChidean
  • 7,941
  • 1
  • 29
  • 33
Jesper
  • 7,477
  • 4
  • 40
  • 57
  • Thanks. But now I got fatal error : Can't unwrap Optional.None – user3806731 Jul 08 '14 at 16:34
  • On the line you want me to add. Do you know what does this mean? – user3806731 Jul 08 '14 at 16:34
  • 3
    That means either that `editingInfo` is `nil` (which I don't think), or that `UIImagePickerControllerOriginalImage` does not exist in the dictionary. You're implementing an old method, you're meant to implement `imagePickerController:didFinishPickingMediaWithInfo:` and not `imagePickerController:didFinishPickingImage:editingInfo:`. – Jesper Jul 08 '14 at 17:14
34

Details

  • Xcode 11.4.1 (11E503a), Swift 5.2

More

How to build own photo picker

Solution

import UIKit
import AVFoundation
import Photos

protocol ImagePickerDelegate: class {
    func imagePicker(_ imagePicker: ImagePicker, grantedAccess: Bool,
                     to sourceType: UIImagePickerController.SourceType)
    func imagePicker(_ imagePicker: ImagePicker, didSelect image: UIImage)
    func cancelButtonDidClick(on imageView: ImagePicker)
}

class ImagePicker: NSObject {

    private weak var controller: UIImagePickerController?
    weak var delegate: ImagePickerDelegate? = nil

    func dismiss() { controller?.dismiss(animated: true, completion: nil) }
    func present(parent viewController: UIViewController, sourceType: UIImagePickerController.SourceType) {
        let controller = UIImagePickerController()
        controller.delegate = self
        controller.sourceType = sourceType
        self.controller = controller
        DispatchQueue.main.async {
            viewController.present(controller, animated: true, completion: nil)
        }
    }
}

// MARK: Get access to camera or photo library

extension ImagePicker {

    private func showAlert(targetName: String, completion: ((Bool) -> Void)?) {
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            let alertVC = UIAlertController(title: "Access to the \(targetName)",
                                            message: "Please provide access to your \(targetName)",
                                            preferredStyle: .alert)
            alertVC.addAction(UIAlertAction(title: "Settings", style: .default, handler: { action in
                guard   let settingsUrl = URL(string: UIApplication.openSettingsURLString),
                        UIApplication.shared.canOpenURL(settingsUrl) else { completion?(false); return }
                UIApplication.shared.open(settingsUrl, options: [:]) { [weak self] _ in
                    self?.showAlert(targetName: targetName, completion: completion)
                }
            }))
            alertVC.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in completion?(false) }))
            UIApplication.shared.windows.filter { $0.isKeyWindow }.first?
                .rootViewController?.present(alertVC, animated: true, completion: nil)
        }
    }

    func cameraAsscessRequest() {
        if delegate == nil { return }
        let source = UIImagePickerController.SourceType.camera
        if AVCaptureDevice.authorizationStatus(for: .video) ==  .authorized {
            delegate?.imagePicker(self, grantedAccess: true, to: source)
        } else {
            AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
                guard let self = self else { return }
                if granted {
                    self.delegate?.imagePicker(self, grantedAccess: granted, to: source)
                } else {
                    self.showAlert(targetName: "camera") { self.delegate?.imagePicker(self, grantedAccess: $0, to: source) }
                }
            }
        }
    }

    func photoGalleryAsscessRequest() {
        PHPhotoLibrary.requestAuthorization { [weak self] result in
            guard let self = self else { return }
            let source = UIImagePickerController.SourceType.photoLibrary
            if result == .authorized {
                DispatchQueue.main.async { [weak self] in
                    guard let self = self else { return }
                    self.delegate?.imagePicker(self, grantedAccess: result == .authorized, to: source)
                }
            } else {
                self.showAlert(targetName: "photo gallery") { self.delegate?.imagePicker(self, grantedAccess: $0, to: source) }
            }
        }
    }
}

// MARK: UINavigationControllerDelegate

extension ImagePicker: UINavigationControllerDelegate { }

// MARK: UIImagePickerControllerDelegate

extension ImagePicker: UIImagePickerControllerDelegate {

    func imagePickerController(_ picker: UIImagePickerController,
                               didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let image = info[.editedImage] as? UIImage {
            delegate?.imagePicker(self, didSelect: image)
            return
        }

        if let image = info[.originalImage] as? UIImage {
            delegate?.imagePicker(self, didSelect: image)
        } else {
            print("Other source")
        }
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        delegate?.cancelButtonDidClick(on: self)
    }
}

Full Usage

Info.plist

 <key>NSPhotoLibraryUsageDescription</key>
 <string>bla-bla-bla</string>
 <key>NSCameraUsageDescription</key>
 <string>bla-bla-bla</string>

ViewController (do not forget to paste solution code)

import UIKit

class ViewController: UIViewController {

    private weak var imageView: UIImageView!
    private lazy var imagePicker: ImagePicker = {
        let imagePicker = ImagePicker()
        imagePicker.delegate = self
        return imagePicker
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "camera", style: .plain, target: self,
                                                           action: #selector(cameraButtonTapped))
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "photo", style: .plain, target: self,
                                                           action: #selector(photoButtonTapped))

        let imageView = UIImageView(frame: CGRect(x: 40, y: 80, width: 200, height: 200))
        imageView.backgroundColor = .lightGray
        view.addSubview(imageView)
        self.imageView = imageView
    }

    @objc func photoButtonTapped(_ sender: UIButton) { imagePicker.photoGalleryAsscessRequest() }
    @objc func cameraButtonTapped(_ sender: UIButton) { imagePicker.cameraAsscessRequest() }
}

// MARK: ImagePickerDelegate

extension ViewController: ImagePickerDelegate {

    func imagePicker(_ imagePicker: ImagePicker, didSelect image: UIImage) {
        imageView.image = image
        imagePicker.dismiss()
    }

    func cancelButtonDidClick(on imageView: ImagePicker) { imagePicker.dismiss() }
    func imagePicker(_ imagePicker: ImagePicker, grantedAccess: Bool,
                     to sourceType: UIImagePickerController.SourceType) {
        guard grantedAccess else { return }
        imagePicker.present(parent: self, sourceType: sourceType)
    }
}

Images

enter image description here


enter image description here


enter image description here


enter image description here


enter image description here


enter image description here

Vasily Bodnarchuk
  • 24,482
  • 9
  • 132
  • 127
24
import MobileCoreServices

class SecondViewController: UIViewController,UINavigationControllerDelegate, UIImagePickerControllerDelegate {

   @IBOutlet var img:UIImageView!=nil

   override func viewDidLoad() {
        super.viewDidLoad()
   }

   override func didReceiveMemoryWarning() 
   {
       super.didReceiveMemoryWarning()

   }

   @IBAction func buttonTapped(AnyObject)
   {
     if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary){
            println("Button capture")
            var imag = UIImagePickerController()
            imag.delegate = self
            imag.sourceType = UIImagePickerControllerSourceType.PhotoLibrary;
            //imag.mediaTypes = [kUTTypeImage];
            imag.allowsEditing = false
            self.presentViewController(imag, animated: true, completion: nil)
        }
   }

   func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
        let selectedImage : UIImage = image
       //var tempImage:UIImage = editingInfo[UIImagePickerControllerOriginalImage] as UIImage
        img.image=selectedImage
        self.dismissViewControllerAnimated(true, completion: nil)    
   }
 }
Kendall Helmstetter Gelner
  • 74,769
  • 26
  • 128
  • 150
  • I guess delegate method is changed to func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) { – Desert Rose Jul 21 '15 at 11:42
  • func imagePickerController didFinishPickingImage editingInfo is deprecated like from iOS 3 https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImagePickerControllerDelegate_Protocol/ – Radek Wilczak Sep 08 '15 at 12:55
12

Since swift 4.2 and xcode 10 the func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) change a bit.

at the function header the infoKey-Section changes from

didFinishPickingMediaWithInfo info: [String : Any] to

didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]

To get the originalImage you now have to call:

let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage or

let image = info[.originalImage] as? UIImage

find other infoKeys here (editedImage, imageURL and more...)

andre_hold
  • 562
  • 8
  • 20
6

In Swift 5.2, iOS 14.2

class YourViewController: UIViewController,UINavigationControllerDelegate, UIImagePickerControllerDelegate {

@IBAction func btnTapped(_ sender: Any) {
    let imagePickerController = UIImagePickerController()
    imagePickerController.allowsEditing = false //If you want edit option set "true"
    imagePickerController.sourceType = .photoLibrary
    imagePickerController.delegate = self
    present(imagePickerController, animated: true, completion: nil)
    
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    let tempImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
    imgRoom.image  = tempImage
    self.dismiss(animated: true, completion: nil)
}

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

}
Naresh
  • 16,698
  • 6
  • 112
  • 113
4

Try this:

func imagePickerController(picker: UIImagePickerController!, didFinishPickingMediaWithInfo info:NSDictionary!) {
    let tempImage = info[UIImagePickerControllerOriginalImage] as! UIImage
    imagePreview.image  = tempImage

or you can also use ? in place of !.

DimaSan
  • 12,264
  • 11
  • 65
  • 75
Gaurav
  • 125
  • 1
  • 9