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

Loading images from a URL and storing them locally using Swift4

我需要从 URL 加载图像并将它们存储在本地,这样它们就不必一遍又一遍地重新加载。我正在处理这个扩展:


    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
        }
    }

我 运行 遇到一个问题,UIImagePNGRepresentation 中的 "loadedImage" 返回错误 "Use of unresolved identifier loadedImage"。我的目标是在本地存储图像的 PNG 表示形式。对此错误的任何建议将不胜感激。

这是一个简单的变量范围问题。您在 do 块内声明 loadedImage 但随后您尝试在该块之外(之后)使用。

loadedImage 的使用移动到 do 块内。

您还需要更好的错误处理和更好的可选结果处理。并且您的 load 方法可能应该 return 一个可选图像,以防所有获取图像的尝试都失败。或者 return 一些默认图像。

这是使用更好的 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
    }
}

如果 eventInfo!.bannerImage 是一个远程 URL,那么你绝不能 运行 这个代码在主队列上。