1

I am facing difficulties storing an image taken from the camera when using UIImagePickerController and getting its URL.

Checking the logs, I think it's because the taken image has no saved path on phone?

let imageUrl          = info[UIImagePickerControllerImageURL] as? NSURL // logs show nil here
...
let localPath         = photoURL.appendingPathComponent(imageName!) // crashes here due to forced unwrap of imageName (nil)

I wonder how I can fix this? I have consulted other answers but none of them work (deprecated libraries or other issues).

More complete code:

func openCamera() {
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            let imagePickerController = UIImagePickerController()
            imagePickerController.delegate = self
            imagePickerController.sourceType = .camera;
            imagePickerController.allowsEditing = false
            present(imagePickerController, animated: true, completion: nil)
        }
    }


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
            fatalError("error message")
        }

        let image = info[UIImagePickerControllerOriginalImage] as! UIImage
        let imageUrl          = info[UIImagePickerControllerImageURL] as? NSURL // logs show nil here
        let imageName         = imageUrl?.lastPathComponent
        let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
        let photoURL          = NSURL(fileURLWithPath: documentDirectory)
        let localPath         = photoURL.appendingPathComponent(imageName!) // crashes here due to forced unwrap of imageName (nil)

        if !FileManager.default.fileExists(atPath: localPath!.path) {
            do {
                try UIImageJPEGRepresentation(image, 1.0)?.write(to: localPath!)
                print("file saved")
            }catch {
                print("error saving file")
            }
        }
        else {
            print("file already exists")
        }

        ...
        dismiss(animated: true, completion: nil)
    }
just a kid
  • 123
  • 1
  • 8
  • where is the error? – CZ54 Jul 25 '18 at 12:24
  • 1
    If you want to save in Photo library: https://stackoverflow.com/questions/178915/how-to-save-picture-to-iphone-photo-library – Venk Jul 25 '18 at 12:25
  • If you want to save in document directory: https://stackoverflow.com/questions/32836862/how-to-use-writetofile-to-save-image-in-document-directory – Venk Jul 25 '18 at 12:25
  • @Venkadesh thanks, i've tried those out. but may I know how to get image url after UIImageWriteToSavedPhotosAlbum(chosenImage, nil, nil, nil) ? especially to store it in info[UIImagePickerControllerImageURL] if possible? – just a kid Jul 25 '18 at 14:19
  • @CZ54 sorry, i've edited the question a bit, is it clearer? – just a kid Jul 25 '18 at 14:20

2 Answers2

0

There is very easy function for this:

UIImageWriteToSavedPhotosAlbum(chosenImage, nil, nil, nil)

But I've also created helper class to deal with this. Thanks to this helper you can save photo in specified album

import Foundation
import Photos

final class PhotoAlbumHelper: NSObject {

    static let albumName = "AppAlbum"
    static let shared = PhotoAlbumHelper()

    var assetCollection: PHAssetCollection?
    var failedPhotos = [UIImage]()

    func fetchAssetCollectionForAlbum() -> PHAssetCollection? {
        let fetchOptions = PHFetchOptions()
        fetchOptions.predicate = NSPredicate(format: "title = %@", PhotoAlbumHelper.albumName)
        let collections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)

        if let collection = collections.firstObject {
            return collection
        }
        return nil
    }

    func createAlbum() {
        PHPhotoLibrary.shared().performChanges({
            PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: PhotoAlbumHelper.albumName) // create an asset collection with the album name
        }) { [weak self] success, error in
            if success {
                guard let `self` = self else { return }
                self.assetCollection = self.fetchAssetCollectionForAlbum()
                while self.failedPhotos.count > 0 {
                    self.saveImage(self.failedPhotos.removeFirst())
                }
            } else {
                print(error)
            }
        }
    }

    func saveImage(_ image: UIImage) {
        assetCollection = fetchAssetCollectionForAlbum()
        if assetCollection == nil {
            failedPhotos.append(image)
            createAlbum()
            return
        }
        guard let album = assetCollection else { return }
        PHPhotoLibrary.shared().performChanges({
            let creationRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
            guard let addAssetRequest = PHAssetCollectionChangeRequest(for: album) else { return }
            let index = IndexSet(integer: 0)
            addAssetRequest.insertAssets([creationRequest.placeholderForCreatedAsset!] as NSArray, at: index)
        }, completionHandler: { success, error in
            if !success {
                print(error)
            }
        })
    }
}
  • may I know how to get image url after UIImageWriteToSavedPhotosAlbum(chosenImage, nil, nil, nil) ? especially to store it in info[UIImagePickerControllerImageURL] if possible? – just a kid Jul 25 '18 at 14:18
0

According to documentation :

A dictionary containing the original image and the edited image, if an image was picked; or a filesystem URL for the movie, if a movie was picked. The dictionary also contains any relevant editing information. The keys for this dictionary are listed in Editing Information Keys.

Link to Documentation

You cannot get the URL ( or you shouldn't ). But you can have the image itself ( either in UIImagePickerControllerEditedImage or in UIImagePickerControllerOriginalImage.

CZ54
  • 5,144
  • 1
  • 20
  • 36
  • Will I be able to get the URL after I saved the image? Or is it not possible at all? I need the URL for storage in Firebase. Thanks! – just a kid Jul 26 '18 at 00:17