0
votes

I am needing to load images from a URL and store them locally so they dont have to be reloaded over and over. I have this extension I am working on:


    extension UIImage {
        func load(image imageName: String) -> UIImage {
            // declare image location
            let imagePath: String = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/\(imageName).png"
            let imageUrl: URL = URL(fileURLWithPath: imagePath)

            // check if the image is stored already
            if FileManager.default.fileExists(atPath: imagePath),
                let imageData: Data = try? Data(contentsOf: imageUrl),
                let image: UIImage = UIImage(data: imageData, scale: UIScreen.main.scale) {
                return image
            }

            // image has not been created yet: create it, store it, return it
            do {
                let url = URL(string: eventInfo!.bannerImage)!
                let data = try Data(contentsOf: url)
                let loadedImage: UIImage = UIImage(data: data)!
            }
            catch{
                print(error)
            }

            let newImage: UIImage = 
                try? UIImagePNGRepresentation(loadedImage)?.write(to: imageUrl)
            return newImage
        }
    }

I am running into a problem where the "loadedImage" in the UIImagePNGRepresentation comes back with an error "Use of unresolved identifier loadedImage". My goal is to store a PNG representation of the image locally. Any suggestions on this error would be appreciated.

1

1 Answers

0
votes

It's a simple matter of variable scope. You declare loadedImage inside the do block but then you attempt to use outside (after) that block.

Move the use of loadedImage to be inside the do block.

You also need better error handling and better handling of optional results. And your load method should probably return an optional image incase all attempts to get the image fail. Or return some default image.

Here's your method rewritten using better APIs and better handling of optionals and errors.

extension UIImage {
    func load(image imageName: String) -> UIImage? {
        // declare image location
        guard let imageUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent(imageName).appendingPathExtension("png") else {
            return nil // or create and return some default image
        }

        // check if the image is stored already
        if FileManager.default.fileExists(atPath: imageUrl.path) {
            if let imageData = try? Data(contentsOf: imageUrl), let image = UIImage(data: imageData) {
                return image
            }
        }

        // image has not been created yet: create it, store it, return it
        do {
            let url = URL(string: eventInfo!.bannerImage)! // two force-unwraps - consider better handling of this
            if let data = try Data(contentsOf: url), let loadedImage = UIImage(data: data) {
                try data.write(to: imageUrl)

                return loadedImage
            }
        }
        catch{
            print(error)
        }

        return nil // or create and return some default image
    }
}

If eventInfo!.bannerImage is a remote URL, then you must never run this code on the main queue.