Pas*_*cal 1 asynchronous image reusability ios swift
我有一个UITable-View,其中包含用户列表及其个人资料图片.我正在为每个玩家异步加载图片(http:// api/pictures / {userid}):
func loadImageAsync(imageUrl: URL, completionHandler handler: @escaping (_ success: Bool, _ image: UIImage?) -> Void){
DispatchQueue.global(qos: .userInitiated).async { () -> Void in
if let imgData = try? Data(contentsOf: imageUrl), let img = UIImage(data: imgData) {
DispatchQueue.main.async(execute: { () -> Void in
handler(true, img)
})
} else {
handler(false, nil)
}
}
Run Code Online (Sandbox Code Playgroud)
在cellForRowAt-Index-Fuction的完成处理程序中,我正在设置图片.
loadImageAsync(imageUrl: imageUrl!, label: ip) { (success, image, backlabel) -> Void in
if(success){
cell.profilePictureView.image = image
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我滚动得非常快时,一些图片会被加载到错误的单元格中.为了防止重用问题,我在每次重用后"重置"图像视图:
override func prepareForReuse() {
profilePictureView.image = UIImage(named: "defaultProfilePicture")
}
Run Code Online (Sandbox Code Playgroud)
但是为什么在快速滚动时仍然会有一些图像加载错误?
嗯,这也是我的想法.
__Update:因此,我使用Label参数(类型为Any)扩展了该函数,该函数在放入函数时返回.我试图将参数(使用索引路径)与当前索引路径进行比较.实际上,这应该工作 - 不应该吗?!
loadImageAsync(imageUrl: imageUrl!, label: ip) { (success, image, backlabel) -> Void in
cell.loader.stopAnimating()
if (backlabel as! IndexPath == indexPath) {
//set image...
Run Code Online (Sandbox Code Playgroud)
但是,它没有显示任何效果.你知道为什么或有任何其他解决方案来解决这个问题吗?
问题是,如果您快速滚动,下载可能需要足够长的时间,在完成时,相关单元格已从屏幕滚动并被回收用于数据模型中的不同indexPath.
诀窍是在完成块中询问表视图中的indexPath处的单元格,并且只有在返回单元格时才安装图像:
loadImageAsync(imageUrl: imageUrl!, label: ip, for indexPath: IndexPath) { (success, image, backlabel) -> Void in
if(success){
let targetCell = tableview.cell(for: indexPath)
targetCell.profilePictureView.image = image
}
}
Run Code Online (Sandbox Code Playgroud)
像这样重新定义loadImageAsync函数:
func loadImageAsync(imageUrl: URL,
indexPath: IndexPath,
completionHandler handler: @escaping (_ success: Bool,
_ image: UIImage?,
_ indexPath: IndexPath ) -> Void) { ... }
Run Code Online (Sandbox Code Playgroud)
顺便说一句,您应该将图像保存到磁盘并从那里加载它们,而不是每次都从Internet加载.我建议使用图像URL的哈希值作为文件名.
修改loadImageAsync,如下所示:
检查磁盘上是否已存在该文件.如果是这样,请加载并返回.
如果该文件不存在,请执行异步加载,然后使用URL的哈希值作为文件名将其保存到磁盘,然后再返回内存中的映像.
| 归档时间: |
|
| 查看次数: |
802 次 |
| 最近记录: |