图片下载后更新单元格高度
Updating cell height after image downloads
我正在 UITableView
中显示一些文本和图像。图像首先被下载。因为在下载图片之前,我不知道图片的大小,所以我最初放了一个固定大小的 UIImageView
。下载图片后,我调整 UIImageView
的大小。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Download image
dispatch_async(dispatch_get_main_queue(), ^{
// UIImageView resizing
});
});
这一切都发生在cellForRowAtIndexPath
。
我在这里面临的问题是:
1.如何更新单元格的高度?考虑到单个单元格中可以有很多图像。所以我需要在上面一个下载时更改底部图像的位置。
2. 我尝试使用 UITableView
beginUpdates
和 endUpdates
,但是滚动到单元格的顶部给用户带来了糟糕的体验。
这就是 UI 在 reloadData 上的样子。有5张图片需要下载:UI experience after UITableView reloadData
简答
- 给 space 足够的呼吸给
estimatedRowHeight
- 更改
UITableViewCell
一次 return 由 dequeueReusableCellWithIdentifier
编辑将 不 与缓存单元一起工作
- 使用
reloadRowsAtIndexPaths
触发单个单元重新加载
- 使用 Core Data 管理您的缓存,让
NSFetchedResultsController
样板代码可以完成所有 UI 工作。
详情
没有意外滚动,只在图片出现时更新:
- 如果正在刷新的单元格在或下方水平线,
UITableView
将不滚动
- 如果正在刷新的单元格在上方顶部,
UITableView
将不会滚动
UITableView
仅当单元格清晰可见时才会滚动,和 需要的 space 比可用的多。
让UITableViewAutomaticDimension
努力工作
你需要告诉Cocoa Touch这个cell是stale,这样它就会触发newdequeueReusableCellWithIdentifier
,您将return一个具有适当高度的单元。
无需重新加载整个 table 视图或其部分之一,并假设您的索引为 stable,调用 -tableView:reloadRows:at:with:
传递刚刚更改的单元格的 indexPath,以及 .fade
动画.
代码:
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 250 // match your tallest cell
tableView.rowHeight = UITableViewAutomaticDimension
}
使用URLSession
。当图像可用时,触发 reloadRows:at:with
:
func loadImage(_ url: URL, indexPath: IndexPath) {
let downloadTask:URLSessionDownloadTask =
URLSession.shared.downloadTask(with: url, completionHandler: {
(location: URL?, response: URLResponse?, error: Error?) -> Void in
if let location = location {
if let data:Data = try? Data(contentsOf: location) {
if let image:UIImage = UIImage(data: data) {
self.cachedImages[indexPath.row] = image // Save into the cache
DispatchQueue.main.async(execute: { () -> Void in
self.tableView.beginUpdates()
self.tableView.reloadRows(
at: [indexPath],
with: .fade)
self.tableView.endUpdates()
})
}
}
}
})
downloadTask.resume()
}
进入缓存后,cellForRow
仅从 UI 线程读入:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "id") as! CustomCell
cell.imageView.image = cachedImages[indexPath.row] // Read from the cache
return cell
}
示例:从 *Wikipedia*
中随机获取一组图像
► 在 GitHub and additional details on Swift Recipes 上找到此解决方案。
我正在 UITableView
中显示一些文本和图像。图像首先被下载。因为在下载图片之前,我不知道图片的大小,所以我最初放了一个固定大小的 UIImageView
。下载图片后,我调整 UIImageView
的大小。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Download image
dispatch_async(dispatch_get_main_queue(), ^{
// UIImageView resizing
});
});
这一切都发生在cellForRowAtIndexPath
。
我在这里面临的问题是:
1.如何更新单元格的高度?考虑到单个单元格中可以有很多图像。所以我需要在上面一个下载时更改底部图像的位置。
2. 我尝试使用 UITableView
beginUpdates
和 endUpdates
,但是滚动到单元格的顶部给用户带来了糟糕的体验。
这就是 UI 在 reloadData 上的样子。有5张图片需要下载:UI experience after UITableView reloadData
简答
- 给 space 足够的呼吸给
estimatedRowHeight
- 更改
UITableViewCell
一次 return 由dequeueReusableCellWithIdentifier
编辑将 不 与缓存单元一起工作 - 使用
reloadRowsAtIndexPaths
触发单个单元重新加载
- 使用 Core Data 管理您的缓存,让
NSFetchedResultsController
样板代码可以完成所有 UI 工作。
详情
没有意外滚动,只在图片出现时更新:
- 如果正在刷新的单元格在或下方水平线,
UITableView
将不滚动 - 如果正在刷新的单元格在上方顶部,
UITableView
将不会滚动 UITableView
仅当单元格清晰可见时才会滚动,和 需要的 space 比可用的多。
让UITableViewAutomaticDimension
努力工作
你需要告诉Cocoa Touch这个cell是stale,这样它就会触发newdequeueReusableCellWithIdentifier
,您将return一个具有适当高度的单元。
无需重新加载整个 table 视图或其部分之一,并假设您的索引为 stable,调用 -tableView:reloadRows:at:with:
传递刚刚更改的单元格的 indexPath,以及 .fade
动画.
代码:
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 250 // match your tallest cell
tableView.rowHeight = UITableViewAutomaticDimension
}
使用URLSession
。当图像可用时,触发 reloadRows:at:with
:
func loadImage(_ url: URL, indexPath: IndexPath) {
let downloadTask:URLSessionDownloadTask =
URLSession.shared.downloadTask(with: url, completionHandler: {
(location: URL?, response: URLResponse?, error: Error?) -> Void in
if let location = location {
if let data:Data = try? Data(contentsOf: location) {
if let image:UIImage = UIImage(data: data) {
self.cachedImages[indexPath.row] = image // Save into the cache
DispatchQueue.main.async(execute: { () -> Void in
self.tableView.beginUpdates()
self.tableView.reloadRows(
at: [indexPath],
with: .fade)
self.tableView.endUpdates()
})
}
}
}
})
downloadTask.resume()
}
进入缓存后,cellForRow
仅从 UI 线程读入:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "id") as! CustomCell
cell.imageView.image = cachedImages[indexPath.row] // Read from the cache
return cell
}
示例:从 *Wikipedia*
中随机获取一组图像► 在 GitHub and additional details on Swift Recipes 上找到此解决方案。