Take a photo and save to photo library in Swift

Swift3Ios10

Swift3 Problem Overview


I have a button "take a photo" and when pressed, it opens the camera, you take a photo and when you select "Use Photo", I want it saved to the photo library.

I am able to do all but save to the library. This is the code I have to open the camera:

enter image description here

Swift3 Solutions


Solution 1 - Swift3

Use below code for an image taken from Photo Gallery and save inside photo library.

> Code Support for Swift 3.1 & 4.0 version:

First, we have to do the setup for Permissions inside Project's .plist file:-

  1. Camera

    NSCameraUsageDescription This app will use camera.

  2. Photo Library

    NSPhotoLibraryUsageDescription You can select photos to attach to reports.

  3. Save to Photo Library

    NSPhotoLibraryAddUsageDescription Please allow access to save photo in your photo library


We need to open .pilst file as a Source code type then add permissions inside -

open .plist file


##After That


import UIKit

class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate  {
    
    @IBOutlet weak var imageTake: UIImageView!

  var imagePicker: UIImagePickerController!
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    //MARK: - Take image
    @IBAction func takePhoto(_ sender: UIButton) {
        imagePicker =  UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = .camera
        present(imagePicker, animated: true, completion: nil)
    }

    //MARK: - Saving Image here
    @IBAction func save(_ sender: AnyObject) {
        UIImageWriteToSavedPhotosAlbum(imageTake.image!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
    }
    
    //MARK: - Add image to Library
    func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        if let error = error {
            // we got back an error!
            let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default))
            present(ac, animated: true)
        } else {
            let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default))
            present(ac, animated: true)
        }
    }
    
    //MARK: - Done image capture here
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
         imagePicker.dismiss(animated: true, completion: nil)
        imageTake.image = info[UIImagePickerControllerOriginalImage] as? UIImage
    }
    
}

> #Swift 4.2 Code update -

 class ViewController: UIViewController, UINavigationControllerDelegate  {
    
    @IBOutlet weak var imageTake: UIImageView!
    var imagePicker: UIImagePickerController!
    
    enum ImageSource {
        case photoLibrary
        case camera
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    //MARK: - Take image
    @IBAction func takePhoto(_ sender: UIButton) {
        guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
            selectImageFrom(.photoLibrary)
            return
        }
        selectImageFrom(.camera)
    }
    
    func selectImageFrom(_ source: ImageSource){
        imagePicker =  UIImagePickerController()
        imagePicker.delegate = self
        switch source {
        case .camera:
            imagePicker.sourceType = .camera
        case .photoLibrary:
            imagePicker.sourceType = .photoLibrary
        }
        present(imagePicker, animated: true, completion: nil)
    }
    
    //MARK: - Saving Image here
    @IBAction func save(_ sender: AnyObject) {
        guard let selectedImage = imageTake.image else {
            print("Image not found!")
            return
        }
        UIImageWriteToSavedPhotosAlbum(selectedImage, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
    }
    
    //MARK: - Add image to Library
    @objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        if let error = error {
            // we got back an error!
            showAlertWith(title: "Save error", message: error.localizedDescription)
        } else {
            showAlertWith(title: "Saved!", message: "Your image has been saved to your photos.")
        }
    }
    
    func showAlertWith(title: String, message: String){
        let ac = UIAlertController(title: title, message: message, preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac, animated: true)
    }
 }

 extension ViewController: UIImagePickerControllerDelegate{
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){
        imagePicker.dismiss(animated: true, completion: nil)
        guard let selectedImage = info[.originalImage] as? UIImage else {
            print("Image not found!")
            return
        }
        imageTake.image = selectedImage
    }
}

Solution 2 - Swift3

Anand Nimje's answer updated for Swift 4

class ImageCaptureViewController: UIViewController,UINavigationControllerDelegate,  UIImagePickerControllerDelegate {

@IBOutlet weak var takeImage: UIImageView!
var imagePicker: UIImagePickerController!

@IBAction func takePhoto(_ sender: UIButton) {
    imagePicker = UIImagePickerController()
    imagePicker.delegate = self
    imagePicker.sourceType = .camera
    present(imagePicker, animated: true, completion: nil)
}

@IBAction func savePhoto(_ sender: UIButton) {
    UIImageWriteToSavedPhotosAlbum(takeImage.image!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}

@objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
    if let error = error {
        let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac, animated: true)
    } else {
        let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac, animated: true)
    }
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    imagePicker.dismiss(animated: true, completion: nil)
    takeImage.image = info[UIImagePickerControllerOriginalImage] as? UIImage
}
}

Solution 3 - Swift3

In Swift 3.0

class PhotoViewController: UIViewController, UIGestureRecognizerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate 

create your UIImageView outlets and UIImagePickerController

@IBOutlet weak var userPhotoImageView: UIImageView!
var pickerController = UIImagePickerController()
var imageView = UIImage()

Here i am using tapgesture for clicking on UIImageView

     in viewDidLoad 

    let imageTapGesture = UITapGestureRecognizer(target: self, action: #selector(tapUserPhoto(_:)))
    imageTapGesture.delegate = self
    userPhotoImageView.addGestureRecognizer(imageTapGesture)
    imageTapGesture.numberOfTapsRequired = 1
    userPhotoImageView.isUserInteractionEnabled = true
    pickerController.delegate = self
    func tapUserPhoto(_ sender: UITapGestureRecognizer){
    let alertViewController = UIAlertController(title: "", message: "Choose your option", preferredStyle: .actionSheet)
    let camera = UIAlertAction(title: "Camera", style: .default, handler: { (alert) in
        self.openCamera()
    })
    let gallery = UIAlertAction(title: "Gallery", style: .default) { (alert) in
        self.openGallary()
    }
    let cancel = UIAlertAction(title: "Cancel", style: .cancel) { (alert) in
        
    }
    alertViewController.addAction(camera)
    alertViewController.addAction(gallery)
    alertViewController.addAction(cancel)
    self.present(alertViewController, animated: true, completion: nil)
}
  func openCamera() {
    if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
        pickerController.delegate = self
        self.pickerController.sourceType = UIImagePickerControllerSourceType.camera
        pickerController.allowsEditing = true
        self .present(self.pickerController, animated: true, completion: nil)
    }
    else {
        let alertWarning = UIAlertView(title:"Warning", message: "You don't have camera", delegate:nil, cancelButtonTitle:"OK", otherButtonTitles:"")
        alertWarning.show()
    }
}
func openGallary() {
    if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary) {
        pickerController.delegate = self
        pickerController.sourceType = UIImagePickerControllerSourceType.photoLibrary
        pickerController.allowsEditing = true
        self.present(pickerController, animated: true, completion: nil)
    }
}
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    
    imageView = info[UIImagePickerControllerEditedImage] as! UIImage
    userPhotoImageView.contentMode = .scaleAspectFill
    userPhotoImageView.image = imageView
    dismiss(animated:true, completion: nil)
}
public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
    print("Cancel")
}

Solution 4 - Swift3

import UIKit

class photoPickerController: UIViewController,UINavigationControllerDelegate{

@IBOutlet weak var imageTake: UIImageView!

var imagePicker: UIImagePickerController!
override func viewDidLoad() {
    super.viewDidLoad()
}


@IBAction func takePhoto(_ sender: UIButton) {
    
    imagePicker =  UIImagePickerController()
    imagePicker.delegate = self
    imagePicker.sourceType = .camera
    present(imagePicker, animated: true, completion: nil)
}


@IBAction func saveToLibrary(_ sender: AnyObject) {
    UIImageWriteToSavedPhotosAlbum(imageTake.image!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
    }
}

extension photoPickerController :  UIImagePickerControllerDelegate  {

func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
    if let error = error {
        // we got back an error!
        let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    } else {
        let alert = UIAlertController(title: "Saved!", message: "Image saved successfully", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    }
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    imagePicker.dismiss(animated: true, completion: nil)
    imageTake.image = info[UIImagePickerControllerOriginalImage] as? UIImage
    }
}

Solution 5 - Swift3

Swift 5:

The correct flow to capture and save image.

// 0. Add `NSCameraUsageDescription`, `NSPhotoLibraryUsageDescription` and `NSPhotoLibraryAddUsageDescription` in Info.plist
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    /// the captured image
    private var image: UIImage?
    
    // 1. Check for permissions first
    /// "Take Photo" button action handler
    ///
    /// - parameter sender: the button
    @IBAction func takePhoto(_ sender: UIButton) {
        if AVCaptureDevice.authorizationStatus(for: .video) ==  .authorized {
            self.showPickerWithSourceType(UIImagePickerController.SourceType.camera)
        } else {
            AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) in
                DispatchQueue.main.async {
                    if granted {
                        self.showPickerWithSourceType(UIImagePickerController.SourceType.camera)
                    } else {
                        self.showAlert("No access to camera", message: "You need to grant permissions to camera to take a picture.")
                    }
                }
            })
        }
    }
    
    // 2. Open photo capture
    /// Show image picker
    /// - Parameter sourceType: the type of the source
    private func showPickerWithSourceType(_ sourceType: UIImagePickerController.SourceType) {
        var vc: UIViewController!
        if UIImagePickerController.isSourceTypeAvailable(sourceType) {
            let imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.mediaTypes = [kUTTypeImage as String]       // if you also need a video, then use [kUTTypeImage as String, kUTTypeMovie as String]
            imagePicker.sourceType = sourceType
            imagePicker.videoQuality = UIImagePickerController.QualityType.typeMedium
            vc = imagePicker
        }
        else {
            let alert = UIAlertController(title: "Error", message: "This feature is supported on real devices only", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            vc = alert
        }
        DispatchQueue.main.async {
            UIViewController.getCurrentViewController()?.present(vc, animated: true, completion: nil)
        }
    }
    
    // 3. Temporary save image in `self.image`
    /// Image selected/captured
    /// - Parameters:
    ///   - picker: the picker
    ///   - info: the info
    public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let mediaType = info[UIImagePickerController.InfoKey.mediaType] {
            if (mediaType as AnyObject).description == kUTTypeImage as String {
                if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
                    self.image = image
                }
            }
        }
        picker.dismiss(animated: true, completion: nil)
    }
    
    // 4. Save image
    /// "Save" button action handler
    ///
    /// - parameter sender: the button
    @IBAction func saveImageButtonAction(_ sender: Any) {
        guard let image = self.image else { return }
        UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
    }
    
    
    // Called when image save is complete (with error or not)
    @objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        if let error = error {
            print("ERROR: \(error)")
        }
        else {
            self.showAlert("Image saved", message: "The iamge is saved into your Photo Library.")
        }
    }
    
    /// Show popup with title and message
    /// - Parameters:
    ///   - title: the title
    ///   - message: the message
    private func showAlert(_ title: String, message: String) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        self.present(alert, animated: true, completion: nil)
    }
}

Solution 6 - Swift3

In fact You can just add it to your code and it will save:

UIImageWriteToSavedPhotosAlbum(/* your image */, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)

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

     imagePicker.dismiss(animated: true, completion: nil)
    imageTake.image = info[UIImagePickerControllerOriginalImage] as? UIImage

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLizGView Question on Stackoverflow
Solution 1 - Swift3Anand NimjeView Answer on Stackoverflow
Solution 2 - Swift3mad_greasemonkeyView Answer on Stackoverflow
Solution 3 - Swift3User558View Answer on Stackoverflow
Solution 4 - Swift3Lineesh K MohanView Answer on Stackoverflow
Solution 5 - Swift3Alexander VolkovView Answer on Stackoverflow
Solution 6 - Swift3user8515697View Answer on Stackoverflow