NS操作加载图像到单元格 - 崩溃
即时通讯使用NSOperation下载每个单元格的图像,所以我不会超载用户沉重的图像加载。这工作99%的时间,但不时我得到一个零我的操作块和应用程序崩溃。NS操作加载图像到单元格 - 崩溃
这是代码:
cell.blockImage.image = nil
cell.queue.cancelAllOperations()
let cacheKey = indexPath.row
if(self.imagesDictionary.object(forKey: cacheKey) != nil)
{
cell.blockImage.image = self.imagesDictionary.object(forKey: cacheKey) as? UIImage
}
else
{
let operation: BlockOperation = BlockOperation()
operation.addExecutionBlock({
if let url = NSURL(string: self.arrJSONData[indexPath.row].image) {
if let data = NSData(contentsOf: url as URL) {
if let image: UIImage = UIImage(data: data as Data)
{
self.imagesDictionary.setObject(image, forKey: cacheKey as NSCopying)
DispatchQueue.main.async(execute: {
if(operation.isCancelled)
{
return
}
cell.blockImage.image = image
})
}
}
}
})
cell.queue.addOperation(operation)
}
所以我去下载图像,并将其存储在一个字典中。关键是单元格的indexPath.row。
我也验证图像是否已经在字典中,所以我不再下载它。
而我总是将我的图像设置为零,并在我开始加载单元格时取消BlockOperation。
错误我总是得到的是:
malloc: *** error for object 0x608000244c50: Invalid pointer dequeued from free list
*** set a breakpoint in malloc_error_break to debug
,我总是得到它该块内(但线始终是随机的)
if let image: UIImage = UIImage(data: data as Data)
{
self.imagesDictionary.setObject(image, forKey: cacheKey as NSCopying)
DispatchQueue.main.async(execute: {
if(operation.isCancelled)
{
return
}
cell.blockImage.image = image
})
}
我到底做错了什么?谢谢。
几个问题:
如果使用
NSMutableDictionary
,必须同步与字典中的所有互动。NSMutableDictionary
不是线程安全的。如果您使用NSCache
,它具有非常类似的接口,它提供了线程安全的交互,因此不需要手动同步。此外,你不应该只是更新
cell
里面的操作。您不知道与该索引路径关联的单元格是否仍然可见(或更糟糕的是,它是否已被重新用于其他索引路径)。您应该使用cellForRow(at:)
(不要与名称相似的UITableViewDataSource
方法混淆)以获取与该IndexPath
关联的当前单元格。如果返回非nil
单元格引用,您是否应该使用它来更新单元格的图像。如果它是nil
,则不会更新可见的UIImageView
。-
与您的崩溃无关,如果快速滚动浏览表格视图,您的网络请求队列可能会得到积压,下载不再可见的单元格图像。例如,如果快速滚动到第100行,对可见单元格的请求可能会滞后于对不再可见的前99行的请求。如果他们有低速网络连接(您应该尝试使用“网络链路调节器”进行模拟),这个问题将会被放大。
什么让这更成问题是您正在使用同步,不可取消的网络请求。如果您像EricD所建议的那样使用
UIImageView
扩展中的一个来扩展异步图像检索(例如AlamofireImage,Kingfisher等;这里有很多),则可以减轻此问题。
对不起等了很久,我今天只有时间看看这个问题。那么我最终使用了翠鸟,它为我节省了很多麻烦。谢谢,罗伯! – Gusfat
我不知道为什么你崩溃,但你应该考虑使用类似https://github.com/Alamofire/AlamofireImage – EricD
林外部库不是一个球迷,但我应该研究一下这个库正在做什么。谢谢! – Gusfat