首页 > 解决方案 > 从 URL 加载图像并使用 Swift4 将它们存储在本地

问题描述

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

    扩展 UIImage {
        函数加载(图像图像名称:字符串)-> UIImage {
            // 声明图片位置
            让 imagePath: String = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/\(imageName).png"
            让 imageUrl: URL = URL(fileURLWithPath: imagePath)

            // 检查图像是否已经存储
            如果 FileManager.default.fileExists(atPath: imagePath),
                让 imageData: 数据 = 试试?数据(内容:imageUrl),
                让图像:UIImage = UIImage(数据:imageData,比例:UIScreen.main.scale){
                返回图片
            }

            // 图像尚未创建:创建、存储、返回
            做 {
                让 url = URL(string: eventInfo!.bannerImage)!
                让数据=尝试数据(contentsOf:url)
                让loadedImage:UIImage = UIImage(数据:数据)!
            }
            抓住{
                打印(错误)
            }

            让 newImage: UIImage =
                尝试?UIImagePNGRepresentation(loadedImage)?.write(to: imageUrl)
            返回新图像
        }
    }

我遇到了一个问题,UIImagePNGRepresentation 中的“loadedImage”返回错误“使用未解析的标识符加载图像”。我的目标是在本地存储图像的 PNG 表示。对此错误的任何建议将不胜感激。

标签: iosswiftuiimage

解决方案


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

将使用移动loadedImagedo块内。

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

这是您使用更好的 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,那么您绝不能在主队列上运行此代码。


推荐阅读