iosurlphotokingfisher

Best practice for storing and uploading multiple images from ImagePicker (iOS)


In my application, I have to store and upload multiple photos to a server using the standard iOS UIImagePickerController library. Currently, I am storing working on storing the UIImagePickerControllerReferenceURL for the photo library:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    if let assetURL = info["UIImagePickerControllerReferenceURL"] as? URL {
        assetArray.append(assetURL)   //assetArray globally stored as 'fileprivate var assetArray = [URL]()'
     }
}

However, I just read somewhere that the camera does not provide a "UIImagePickerControllerReferenceURL" key. Thus this method may not work, when I get around to the camera part, so I am re-thinking my logic now.

I am using KingFisher so I am currently researching to see if you can cache images using that framework, but I am not certain. I'm also reading that I could grab the camera image's URL using the Photo's API, which I will attempt next. If I could, I will grab the url of the the photo taken by the camera, and append it to the assetArray.

Had this be a single photo upload, this would be relatively simple, but since I do not want to hinder the performance of the application by storing a large data/image array, this task has become complex.

Is it best to continue what I am doing:

  1. Grab URL's of each image I want to upload, and storing them into an URL array. Before uploading to the server, grab the data in .png form of each URL, and upload images to server

  2. Cache actual images somewhere, so when uploading to server, images will already be there (not needed to be converted from URL -> image). Issue here is having many images may hinder app performance if not done correctly.

or

  1. Some other method

Solution

  • I found a solution using Kingfisher. First, I created an ImageCache object for the VC handling the multiple photos (you need to import Kingfisher):

    fileprivate var imageCache: ImageCache = ImageCache(name: "newTaskCache")
    

    After I select the photo using UIImagePickerController, I save the unique ID in a string array, cachedImageIDs:

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        let image : UIImage = (info[UIImagePickerControllerOriginalImage] as? UIImage)!
        let imageID: String?
        if let assetURL = info["UIImagePickerControllerReferenceURL"] as? URL {
            imageID = assetURL.absoluteString
            cachedImageIDs.append(imageID!)
        }else{
            //camera does not return a UIImagePickerControllerReferenceURL, so unique imageID will be posix time, until I figure out how to get imageURL string
            imageID = String(describing: Date().posixTime())
            cachedImageIDs.append(imageID!)
        }
    
        imageCache.store(image, forKey: imageID!) {
            print("saved image")
            picker.dismiss(animated: true, completion: nil)
        }
    }
    

    When I need to retrieve the images, they are

    func getImages() {
        for id in cachedImageIDs {
            //retrieve image
            imageCache.retrieveImage(forKey: id, options: nil, completionHandler: { (image, cacheType) -> () in
                print(image)
            })
        }
    }