Search code examples
swiftxcodecameramemberphotolibrary

Allowing user to select image from Camera, Photo Library or Photo Albums and hit an error I cannot solve


I've been following David Thorn's video to allow users to take an image using their camera or import from their photo library or photo albums.

https://www.youtube.com/watch?v=wDzk5KDe6Uw

I've followed the guide character by character and am hit with the errors in the image below. I've compared my code to the code in the Github for the tutorial and I cannot find a resolution.

Here is a screen shot of the errors(not enough reputation to embed in post)

Errors are

1! Value of type 'ViewController' has no member 'selectedImage'

2! nil cannot be assigned to type '(UIImagePickerController, [UIImagePickerController.InfoKey : Any]) -> ()'

2! 'nil' cannot be assigned to type '(UIImagePickerController, [UIImagePickerController.InfoKey : Any]) -> ()'

the .swift file is of type UIViewController.

Here is my code entered;

public var imagePickerController: UIImagePickerController?

public var defaultImageUrl: URL?

   internal var selectedImage: UIImage? {
       get {
           return self.selectedImageView.image
       }

       set {
           switch newValue {
           case nil:
               self.selectedImageView.image = nil
               self.selectImageButton.isEnabled = true
               self.selectImageButton.alpha = 1

               self.removeImageButton.isEnabled = false
               self.removeImageButton.alpha = 0.5
           default:
               self.selectedImageView.image = newValue
               self.selectImageButton.isEnabled = false
               self.selectImageButton.alpha = 0.5

               self.removeImageButton.isEnabled = true
               self.removeImageButton.alpha = 1
           }
       }
   }
//This outlet, 'selectedImageContainer' was guessed from observing the tutorial stacked their UIImageView in a UIView.

@IBOutlet weak var selectedImageContainer: UIView!
@IBOutlet weak var selectedImageView: UIImageView!


@IBOutlet weak var selectImageButton: UIButton! {
    didSet {
        guard let button = self.selectImageButton else { return }
        button.isEnabled = true
        button.alpha = 1
    }
}

@IBOutlet weak var removeImageButton: UIButton! {
    didSet {
        guard let button = self.removeImageButton else { return }
        button.isEnabled = false
        button.alpha = 0.5
    }

override func viewDidLoad() {
super.viewDidLoad()
self.selectedImageView.contentMode = .scaleAspectFit
self.selectImageButton.isEnabled = self.selectedImage == nil
self.selectImageButton.alpha = 1

}


@IBAction func selectImageButtonAction(_ sender: Any) {


    if self.imagePickerController != nil {
        self.imagePickerController?.delegate = nil
        self.imagePickerController = nil
    }
    self.imagePickerController = UIImagePickerController.init()

    let alert = UIAlertController.init(title: "Select Source Type", message: nil, preferredStyle: .actionSheet)

    if UIImagePickerController.isSourceTypeAvailable(.camera) {
        alert.addAction(UIAlertAction.init(title: "Camera", style: .default, handler: { (_) in
            self.presentImagePicker(controller: self.imagePickerController!, source: .camera)
        }))
    }

    if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
        alert.addAction(UIAlertAction.init(title: "Photo Library", style: .default, handler: { (_) in
            self.presentImagePicker(controller: self.imagePickerController!, source: .photoLibrary)
        }))
    }

    if UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum) {
        alert.addAction(UIAlertAction.init(title: "Saved Albums", style: .default, handler: { (_) in
            self.presentImagePicker(controller: self.imagePickerController!, source: .savedPhotosAlbum)
        }))
    }

    alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel))

    self.present(alert, animated: true)
}

internal func presentImagePicker(controller: UIImagePickerController , source: UIImagePickerController.SourceType) {
    controller.delegate = self
    controller.sourceType = source
    self.present (controller, animated: true)
}

@IBAction func removeImageButtonAction(_ sender: UIButton) {
    self.selectedImage = nil
}


}

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

    guard let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else {
        return self.imagePickerControllerDidCancel(picker)
    }

    self.selectedImage = image

    picker.dismiss(animated: true) {
        picker.delegate = nil
        self.imagePickerController = nil
    }
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
     picker.dismiss(animated: true) {
        picker.delegate = nil
        self.imagePickerController = nil
    }
}
}

Solution

  • I've answered my own question!

    the extension class ViewController was incorrectly named. My .swift file was named something else.

    I also moved the UIImageViewControllerDelegate and the UINavigatonControllerDeletage from the original class at the top of the code so it only appeared in the extension!