[英]Table cell frame not updated after Image downloaded asynchronously
I have a UITableViewCell with UITableViewAutomaticDimension which consists of Image and title.我有一个带有 UITableViewAutomaticDimension 的 UITableViewCell,它由图像和标题组成。 After I get the data from API, I reload tableView, but only title in UILabel appears and not the image, as in below image
从API获取数据后,我重新加载tableView,但只显示UILabel中的标题而不显示图像,如下图
After i scroll the tableView, the images appear and are adjusted according to there size.在我滚动 tableView 后,图像出现并根据那里的大小进行调整。 Like Below
喜欢下面
I want this to happen before scrolling.我希望在滚动之前发生这种情况。
Things I have tried already我已经尝试过的事情
My cellForRowAt Code我的 cellForRowAt 代码
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: Constants.custom.rawValue) as? CustomCell else {return UITableViewCell()}
cell.update(model: arrImages[indexPath.row])
return cell
}
My Cell Class Logic我的单元格类逻辑
Update Method更新方法
func update(model: ImageModel) {
self.presentModel = model
}
UI Changes in cell单元格中的 UI 更改
var presentModel: ImageModel? {
didSet{
if let url = presentModel?.imgURL {
imgView.kf.indicatorType = .activity
imgView.kf.setImage(with: url)
}
lblTitle.text = presentModel?.title
}
}
Addition info I am using KingFisher third party to download images.附加信息我正在使用 KingFisher 第三方下载图像。
You should reload your table view once image is loaded from the url. 从网址加载图片后,您应该重新加载表格视图。
You might have multiple cells with image on each cell. 您可能有多个单元格,每个单元格上都有图像。 So you should call the tableView's reload method once your image is downloaded from the url asynchronously.
因此,一旦从url中异步下载了图片,就应该调用tableView的reload方法。
You said that images are appears properly when you scroll down the cells off and on screens, because the tableView's func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) will be called when cell is about to visible on screen. 您说过,当您向下或向下滚动屏幕上的单元格时,图像会正确显示,因为当单元格即将在屏幕上可见时,将调用tableView的func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)。
So you should call tableView.reloadData()
or tableView.reloadRows(at: [imageLoadedCellIndexPath], with: .automatic)
method to trigger the tableview's delegate and data source methods. 因此,您应该调用
tableView.reloadData()
或tableView.reloadRows(at: [imageLoadedCellIndexPath], with: .automatic)
方法来触发tableview的委托和数据源方法。
As you are using Kingfisher extensions to download images from url, you can try using the below method to know the download status. 当您使用Kingfisher扩展程序从url下载图像时,可以尝试使用以下方法来了解下载状态。
imageView.kf.setImage(with: url, completionHandler: {
(image, error, cacheType, imageUrl) in
})
instead of imageView.kf.setImage(with: url).
而不是
imageView.kf.setImage(with: url).
Example: 例:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: Constants.custom.rawValue) as? CustomCell else {return UITableViewCell()}
cell.update(model: arrImages[indexPath.row])
let imageModel = arrImages[indexPath.row]
if let url = imageModel?.imgURL {
//Check if image is already downloaded
ImageCache.default.retrieveImage(forKey: url.absoluteString, options: nil) {
image, cacheType in
//Image is already downloaded
if let image = image {
//cell.imgView.image = image
imgView.kf.setImage(with: url) //try this line instead of above one
} else { //Download
imgView.kf.indicatorType = .activity
cell.imgView.kf.setImage(with: url, completionHandler: {
(image, error, cacheType, imageUrl) in
if image != nil{
tableView.reloadRows(at: [indexPath], with: .automatic)
//OR
tableView.reloadData()
}
})
}
}
}
return cell
}
And Comment image download code in cell as like below, 并在单元格中添加注释图像下载代码,如下所示,
var presentModel: ImageModel? {
didSet{
// if let url = presentModel?.imgURL {
// imgView.kf.indicatorType = .activity
// imgView.kf.setImage(with: url)
// }
lblTitle.text = presentModel?.title
}
}
Do following做以下
Add a stack view inside you table cell在表格单元格内添加堆栈视图
Add add height constraint to the stack view向堆栈视图添加添加高度约束
Create IBOutale of this height constraint创建此高度约束的 IBOutale
load image with the URL using kingfisher SDK with completion block.使用带完成块的 kingfisher SDK 加载带有 URL 的图像。
Inside completion block calculate the height you want to set to your image view内部完成块计算要设置为图像视图的高度
Create UIImageView with frame using the calculated height and width.使用计算的高度和宽度创建带有框架的 UIImageView。
Add ImageView as arrangedsubView in your stack view在您的堆栈视图中添加 ImageView 作为排列子视图
set the constant value of constrain to your calculated height将约束的常量值设置为您计算出的高度
add these two lines after adding ImageView to stack view将 ImageView 添加到堆栈视图后添加这两行
stackView.setNeedsLayout() stackView.layoutIfNeeded() sample code stackView.setNeedsLayout() stackView.layoutIfNeeded() 示例代码
let imageSize = image.size
let width = UIScreen.main.bounds.width - 20
let height = (width * imageSize.height) / imageSize.width
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
imageView.image = image
heightConstraint.constant = height
stackView.addArrangedSubview(imageView)
stackView.setNeedsLayout()
stackView.layoutIfNeeded()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.