我需要从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”返回错误“使用未解析的标识符loadedImage”。我的目标是在本地存储图像的PNG表示。对此错误的任何建议将不胜感激。
这是一个简单的变量范围问题。你在loadedImage
块中声明了do
但是你试图在那个块之外使用(之后)。
将loadedImage
的使用移到do
区域内。
您还需要更好的错误处理和更好地处理可选结果。并且你的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,则必须永远不要在主队列上运行此代码。