简体   繁体   English

从URL加载图像并使用Swift4在本地存储它们

[英]Loading images from a URL and storing them locally using Swift4

I am needing to load images from a URL and store them locally so they dont have to be reloaded over and over. 我需要从URL加载图像并将它们存储在本地,这样就不必一遍又一遍地重新加载它们。 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". 我遇到了一个问题,UIImagePNGRepresentation中的“loadedImage”返回错误“使用未解析的标识符loadedImage”。 My goal is to store a PNG representation of the image locally. 我的目标是在本地存储图像的PNG表示。 Any suggestions on this error would be appreciated. 对此错误的任何建议将不胜感激。

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. 您在do块中声明了loadedImage ,但之后您尝试在该块之外使用(之后)。

Move the use of loadedImage to be inside the do block. loadedImage的使用loadedImage do块内。

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. 并且你的load方法应该返回一个可选的图像,包括所有尝试使图像失败。 Or return some default image. 或返回一些默认图像。

Here's your method rewritten using better APIs and better handling of optionals and errors. 这是使用更好的API以及对可选项和错误的更好处理重写的方法。

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. 如果eventInfo!.bannerImage是远程URL,则您绝不能在主队列上运行此代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM