0

I am relatively new to iOS and would appreciate any help figuring out how to create an array of images when using an extension to help manage downloads and caching. I've been going around in circles with this for a couple hours so thought it was time to tap into the brain trust.

I created an extension of UIImageView in order to download and cache images like this:

let imageCache = NSCache()

extension UIImageView {

func loadImageUsingCacheWithURLString(url: NSURL) {

    self.image = nil

    // First check if there is an image in the cache
    if let cachedImage = imageCache.objectForKey(url) as? UIImage {

        self.image = cachedImage

        return
    }

    else {
    // Otherwise download image using the url location in Google Firebase
    NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, response, error) in

        if error != nil {
            print(error)
        }
        else {
            dispatch_async(dispatch_get_main_queue(), {

                // Cache to image so it doesn't need to be reloaded every time the user scrolls and table cells are re-used.
                if let downloadedImage = UIImage(data: data!) {

                    imageCache.setObject(downloadedImage, forKey: url)
                    self.image = downloadedImage

                }
            })
        }
    }).resume()
    }
}

...so that works great for loading collection view images. However, I also want to capture an array of the images so I can pass it onto another view controller and not need to download everything again (waste of data). I created another function to do this, but imageholder.image is always nil. I don't think it's an async issue because all the images are cached at this point and when I debug I can never get it to not be nil.

var imageHolder: UIImageView!
var imagesArray:[UIImage] = [UIImage]()

// Function to create images array to use on the photo view.
func createImagesArray() {

    for url in imagesURLArray {

        imageHolder.loadImageUsingCacheWithURLString(url)

        if imageHolder.image != nil {

        imagesArray.append(imageHolder.image!)
        }

    }
}

It feels like I am missing something simple, but I'm stuck. Thank you!

Ben
  • 3,346
  • 6
  • 32
  • 51
  • You just use a library for this. consider https://github.com/Haneke/HanekeSwift https://github.com/onevcat/Kingfisher etc. – Fattie May 02 '17 at 11:14

2 Answers2

2

I ended up create another function for the extension that returned a UIImage. After doing that there was not problem appending to the imagesArray.

let imageCache = NSCache()
var returnImage:UIImage = UIImage()

func returnImageUsingCacheWithURLString(url: NSURL) -> (UIImage) {

    // First check if there is an image in the cache
    if let cachedImage = imageCache.objectForKey(url) as? UIImage {

        return cachedImage
    }

    else {
        // Otherwise download image using the url location in Google Firebase
        NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, response, error) in

            if error != nil {
                print(error)
            }
            else {
                dispatch_async(dispatch_get_main_queue(), {

                    // Cache to image so it doesn't need to be reloaded everytime the user scrolls and table cells are re-used.
                    if let downloadedImage = UIImage(data: data!) {

                        imageCache.setObject(downloadedImage, forKey: url)
                        returnImage = downloadedImage

                    }
                })
            }
        }).resume()
        return returnImage
    }
}
Ben
  • 3,346
  • 6
  • 32
  • 51
0
let imageCache = NSCache()
let images:[UIImages] = []

extension UIImageView {

func loadImageUsingCacheWithURLString(url: NSURL) {

    self.image = nil

    // First check if there is an image in the cache
    if let cachedImage = imageCache.objectForKey(url) as? UIImage {

        self.image = cachedImage

        return
    }

    else {
    // Otherwise download image using the url location in Google Firebase
    NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, response, error) in

        if error != nil {
            print(error)
        }
        else {
            dispatch_async(dispatch_get_main_queue(), {

                // Cache to image so it doesn't need to be reloaded every time the user scrolls and table cells are re-used.
                if let downloadedImage = UIImage(data: data!) {

                    imageCache.setObject(downloadedImage, forKey: url)
                    self.image = downloadedImage

                }
            })
        }
        }).resume()
    }
    //Creat array and append the last image to it. 
    self.images.append(self.image)
}
impression7vx
  • 1,728
  • 1
  • 20
  • 50
  • Unfortunately, I'm not following. I see you added let images:[UIImages] = [] (typo: UIImage). – Ben Jul 26 '16 at 21:03
  • Yea, typo , my bad. Then at the bottom, just add the image to the array. – impression7vx Jul 26 '16 at 21:06
  • So all that is happening, is that after you call `self.image = ...` then save the image to an array. badaboom badabang – impression7vx Jul 26 '16 at 21:07
  • Ah I see. Makes sense, but I actually need to do as two separate calls because I sort the URL array (not shown) to match a certain order before I build this array. I didn't make this clear on the first pass. I supposed I could still do that as second call to write over the first array. That said, I think I figured out a solution so posting in a minute... – Ben Jul 26 '16 at 21:37