从 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,那么你绝不能 运行 这个代码在主队列上。
我需要从 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,那么你绝不能 运行 这个代码在主队列上。