1
votes

I am Swift beginner and just completed my Photo camera function in my app. The problem which I have now is that when I take a photo from the camera, it is not saved into the photo library on my iPhone. Everything works perfectly I am able to take pictures, but when I check in Photos, it seems that they are not saved. I had checked for similar questions, but I haven't found a proper answer, I see that they are people who add buttons to access the photo library directly but I do not need such a button. The only function, I require is taking a picture and when the user clicks select photo to save it in the Photos.

So far I have used this:

class ViewController: UIViewController, UIImagePickerControllerDelegate,UINavigationControllerDelegate{



 let imagePicker: UIImagePickerController! = UIImagePickerController()

   override func viewDidLoad() {

    super.viewDidLoad()

    imagePicker.delegate = self

    let upSwipe = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipes))

    upSwipe.direction = .up

    view.addGestureRecognizer(upSwipe)

}

and the function:

func handleSwipes(sender:UISwipeGestureRecognizer) {

        if (sender.direction == .up){

            if ( UIImagePickerController.isSourceTypeAvailable(.camera)){



                if UIImagePickerController.availableCaptureModes(for: .rear) != nil {
                    imagePicker.allowsEditing = false
                    imagePicker.sourceType = .camera
                    imagePicker.cameraCaptureMode = .photo
                    present(imagePicker,animated: true, completion: {})
       }
            }

Here is what I get on my iPhone: I only want when the user chooses to use the photo, the photo itself to be saved in the gallery, as simple as that. enter image description here

6

6 Answers

7
votes

Before anything you need to have the "Privacy - Photo Library Additions Usage Description" to your info.plist otherwise your app will crash

Use this:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage{
            UIImageWriteToSavedPhotosAlbum(pickedImage, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)

            dismiss(animated: true, completion: nil)
        }
    }

And then, add the following function (The same function that saltTigerK wrote)

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)
    }
}

Source: https://www.hackingwithswift.com/read/13/5/saving-to-the-ios-photo-library

2
votes

Swift 5

Clear solution without rubbish:

    /// Save `image` into Photo Library
    UIImageWriteToSavedPhotosAlbum(image, self,
        #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)

    /// Process photo saving result    
    @objc func image(_ image: UIImage,
        didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        if let error = error {
            print("ERROR: \(error)")
        }
    }

Don't forget to add NSPhotoLibraryAddUsageDescription key in your Info.plist

0
votes
...
UIImageWriteToSavedPhotosAlbum(imageView.image!, self, "image:didFinishSavingWithError:contextInfo:", nil) 
...



func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>) {
    if error == nil {
        let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .Alert)
        ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
        presentViewController(ac, animated: true, completion: nil)
    } else {
        let ac = UIAlertController(title: "Save error", message: error?.localizedDescription, preferredStyle: .Alert)
        ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
        presentViewController(ac, animated: true, completion: nil)
    }
}

You can use this function in your project

0
votes

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
}

}

0
votes
class WethioImageSaver: NSObject {

func writeToPhotoAlbum(image: UIImage) {
    let newImagePNG = image.pngData()
    let saveableImage = UIImage(data: newImagePNG!)
    UIImageWriteToSavedPhotosAlbum(saveableImage!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}

@objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
    if let error = error {
        // we got back an error!
        print(error)
       
    } else {
        print("Sucess")
    }
}

}

Before saving the image to photo lib

  1. update info.plist for photolibraryusagedescription
  2. you can't save image directly convert that into png and then uiimage
-2
votes

Every Apps have its own storage at Document directory. In Document directory user can store audio,video,image,pdf and others files without collide to the others apps. and you can also read and write data of particular apps of Document directory.

Document directory store the user data or file at path of apps. All files are store the folder of particular app. You can read apps data from the path of document directory.

Save Image At Document Directory :

func saveImageDocumentDirectory(){

let fileManager = NSFileManager.defaultManager()

let paths = (NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString).stringByAppendingPathComponent(“apple.jpg”)

let image = UIImage(named: “apple.jpg”)

print(paths)

let imageData = UIImageJPEGRepresentation(image!, 0.5) fileManager.createFileAtPath(paths as String, contents: imageData, attributes: nil)

}

Get Document Directory Path :

func getDirectoryPath() -> String {

let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)

let documentsDirectory = paths[0] return documentsDirectory

}

Get Image from Document Directory :

func getImage(){

let fileManager = NSFileManager.defaultManager()

let imagePAth = (self.getDirectoryPath() as NSString).stringByAppendingPathComponent(“apple.jpg”)

if fileManager.fileExistsAtPath(imagePAth){

self.imageView.image = UIImage(contentsOfFile: imagePAth)

}else{

print(“No Image”)

}

}

Create Directory :

func createDirectory(){

let fileManager = NSFileManager.defaultManager()

let paths = (NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString).stringByAppendingPathComponent(“customDirectory”)

if !fileManager.fileExistsAtPath(paths){

try! fileManager.createDirectoryAtPath(paths, withIntermediateDirectories: true, attributes: nil)

}else{

print(“Already dictionary created.”)

}

}

Delete Directory :

func deleteDirectory(){

let fileManager = NSFileManager.defaultManager()

let paths = (NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString).stringByAppendingPathComponent(“customDirectory”)

if fileManager.fileExistsAtPath(paths){

try! fileManager.removeItemAtPath(paths)

}else{

print(“Something wronge.”)

}

}