NSCache不适用于第一次加载时的所有图像
我在swift 3.0中的项目上工作,我使用NSCache缓存来自服务器的响应,将它们填充到UITableView中。然而,由于某种原因,我第一次看到应用程序加载时加载的图像很少,但如果如果我滚动并返回,我会看到所有内容(从服务器检索响应的结尾,我也重新加载了我的tableview,但看起来像不是这种情况)。我不知道我在这里完全错过了什么,代码如下,以显示我如何缓存图像。NSCache不适用于第一次加载时的所有图像
let imageCache = NSCache<AnyObject, AnyObject>()
var imageURLString : String?
extension UIImageView {
public func imageFromServerURL(urlString: String) {
imageURLString = urlString
if let url = URL(string: urlString) {
image = nil
if let imageFromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
self.image = imageFromCache
return
}
URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
if error != nil{
print(error as Any)
return
}
DispatchQueue.main.async(execute: {
if let imgaeToCache = UIImage(data: data!){
if imageURLString == urlString {
self.image = imgaeToCache
}
imageCache.setObject(imgaeToCache, forKey: urlString as AnyObject)// calls when scrolling
}
})
}) .resume()
}
}
}
这里图像下载并存储在缓存中就好了。问题在于桌面单元的更新。
当表格视图将单元格加载到表格上时,图像尚未下载。但一旦下载图像,我们必须有选择地更新单元格,以便图像即时显示。
由于您正在滚动,tableview会再次调用'cellForRowatIndexpath',它会在滚动时更新显示下载图像的单元格。
如果您仍然希望使用扩展名,我建议您添加tableView和indexpath作为参数,以便我们可以调用重新加载特定行并立即更新视图。
我已经更新了扩展中定义的函数的表重载代码和结构。让我知道事情的后续。
let imageCache = NSCache<AnyObject, AnyObject>()
var imageURLString : String?
extension UIImageView {
public func imageFromServerURL(urlString: String, tableView : UITableView, indexpath : IndexPath)) {
imageURLString = urlString
if let url = URL(string: urlString) {
image = nil
if let imageFromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
self.image = imageFromCache
return
}
URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
if error != nil{
print(error as Any)
return
}
DispatchQueue.main.async(execute: {
if let imgaeToCache = UIImage(data: data!){
if imageURLString == urlString {
self.image = imgaeToCache
}
imageCache.setObject(imgaeToCache, forKey: urlString as AnyObject)// calls when scrolling
tableView.reloadRows(at: [indexpath], with: .automatic)
}
})
}) .resume()
}
}
我有一个示例项目,使用简单的swift 3进行json解析。您可以在这里参考: [link](https:// github。 com/PmAbi1993/Json-Parser) –
太棒了!!就像一个魅力!! –
但它会导致tableview滚动到顶部每次单元格加载。 –
我认为这将使用子类,而不是延长,是一种更好的方法(以从Jageen的评论帮助,因为我们不能包含内部存储的扩展性能,所以我们使用了封装的想法)
let imageCache = NSCache<AnyObject, AnyObject>()
class CustomImageView: UIImageView {
var imageUrlString: String?
func loadImageUsingUrlString(_ urlString: String) {
let url = URL(string: urlString)
imageUrlString = urlString
image = nil
if let imageFromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
self.image = imageFromCache
return
}
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print(error!)
return
}
DispatchQueue.main.async {
let imageToCache = UIImage(data: data!)
if self.imageUrlString == urlString {
self.image = imageToCache
}
imageCache.setObject(imageToCache!, forKey: urlString as AnyObject)
}
}.resume()
}
}
- 现在使用这个子类作为你在屏幕上显示的图像类型
这对我来说非常合适,以及来自Brian Voong的YouTube用户的指导! –
我的主要嫌疑人是imageURLString,因为它是全局变量,您将它与本地变量进行比较,但是您会为每个请求进行更改。 Y?确保这一点,为了什么你的目的,你写这个(如果imageURLString == urlString)是工作,因为你的期望和更多只是检查你的逻辑适用于只有一个图像? – Jageen
我认为这段代码是正确的,并且图像需要时间来加载,因为它们来自服务器,我认为如果你不滚动图像将仍然加载 – 3stud1ant3
否,如果我不滚动它不会炒锅:( – danu