为啥调用 reloadRows 后,heightForRowAt 没有在数组中找到值?
Posted
技术标签:
【中文标题】为啥调用 reloadRows 后,heightForRowAt 没有在数组中找到值?【英文标题】:Why doesntnt heightForRowAt find a value in the array after reloadRows is called?为什么调用 reloadRows 后,heightForRowAt 没有在数组中找到值? 【发布时间】:2018-01-15 18:11:30 【问题描述】:为什么函数heightForRowAt
总是找到包含行高的数组,该数组最初设置为 nil,即使在重新加载行后仍然为零。
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "Reuse", for: indexPath) as! TableViewCell
let downloadURL = URL(string: self.imageURLS[indexPath.row])
if cell.cellImageView.image == nil
URLSession.shared.dataTask(with: downloadURL!) (data, _, _) in
if let data = data
let image = UIImage(data: data)
DispatchQueue.main.async
cell.setCellImage(image:image!)
self.rowHeights?.insert((cell.imageView?.frame.height)!, at: indexPath.row)
tableView.reloadRows(at: [indexPath], with: .top)
.resume()
return cell
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
guard let rowHeights = self.rowHeights else
print("returned nil")
return 500.0
print("the array exists at \(indexPath.row) with value: \(rowHeights[indexPath.row])")
return rowHeights[indexPath.row]
更新的 TableViewController
import UIKit
import Firebase
import FirebaseStorageUI
class TableViewController: UITableViewController
var images:[UIImage]! = [#imageLiteral(resourceName: "rininger_2.jpg")]
var imageURLS:[String] = [String]()
var rowHeights:[CGFloat] = [CGFloat]()
var listener:ListenerRegistration?
override func viewDidLoad()
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
listener = Firestore.firestore().collection("Posts").addSnapshotListener
querySnapshot, error in
guard let snapshot = querySnapshot else
print("Error fetching snapshots: \(error!)")
return
snapshot.documentChanges.forEach diff in
if (diff.type == .added)
print("New data: \(diff.document.data())")
if (diff.type == .modified)
print("Modified data: \(diff.document.data())")
if (diff.type == .removed)
print("Removed data: \(diff.document.data())")
guard let newImageURL = diff.document.data()["imageDownloadURL"] as? String else
print("Failed to get image download URL")
return
print("downloadURL: \(newImageURL)")
self.imageURLS.insert(newImageURL, at: 0)
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.insertRows(at: [indexPath], with: .top)
tableView.estimatedRowHeight = 100.0
tableView.rowHeight = UITableViewAutomaticDimension
override func numberOfSections(in tableView: UITableView) -> Int
return 1
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return imageURLS.count
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "Reuse", for: indexPath) as! TableViewCell
let downloadURL = URL(string: self.imageURLS[indexPath.row])
if cell.cellImageView.image == nil
URLSession.shared.dataTask(with: downloadURL!) (data, _, _) in
if let data = data
let image = UIImage(data: data)
self.images.insert(image, at: indexPath.row)
DispatchQueue.main.async
cell.setCellImage(image:image!)
// self.rowHeights.insert((cell.imageView?.frame.height)!, at: indexPath.row)
//tableView.reloadData()
tableView.reloadRows(at: [indexPath], with: .top)
.resume()
return cell
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
print("UITableViewAutomaticDimension: \(UITableViewAutomaticDimension)")
return UITableViewAutomaticDimension
【问题讨论】:
你是怎么申报的? @Sh_Khan 它在UITableViewController
类的顶部声明为var rowHeights:[CGFloat]? = nil
,并且不在cellForRowAt
或heightForRowAt
之外使用
必须像那样 var rowHeights = [CGFloat]()
为什么还要发布另一个问题(两天内现在有 8 个)而不是更新您的 previous question?
请注意,如果先加载第二张图片,您可能会崩溃...(请参阅此处的说明:***.com/questions/48170210/…
【参考方案1】:
您的代码存在大量问题
1-首先你必须下载,保存图像,然后重新加载表格
2- 秒您应该使用自动表格视图高度来完成此操作,而不是像您当前所做的那样使用高度数组
解决1
NSString *getImagePath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.jpeg",n1.Id]];
if([[NSFileManager defaultManager] fileExistsAtPath:getImagePath])
UIImage *img = [UIImage imageWithContentsOfFile:getImagePath];
cell.leftImageV.image =img;
[cell.activity stopAnimating];
cell.activity.hidden=YES;
else
[cell.activity startAnimating];
cell.activity.hidden=NO;
cell.leftImageV.image = nil;
NSLog(@"xdasdxsadxa %@",n1.mainImgStr);
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^
__block NSData * imageData = nil;
dispatch_sync(concurrentQueue, ^
imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:n1.mainImgStr]];
//Add the file name
[imageData writeToFile:getImagePath atomically:YES]; //Write the file
);
dispatch_sync(dispatch_get_main_queue(), ^
if(imageData)
[self.tableView reloadData];
);
);
解决 2
要设置行高和估计行高的自动尺寸,请确保执行以下步骤,自动尺寸对单元格/行高布局有效。我刚刚测试了以下步骤和代码并且工作正常。
分配和实现 tableview 数据源和委托 将UITableViewAutomaticDimension
分配给rowHeight 和estimatedRowHeight
实现委托/数据源方法(即heightForRowAt
并向其返回值UITableViewAutomaticDimension
)
-
@IBOutlet weak var table: UITableView!
override func viewDidLoad()
super.viewDidLoad()
// Don't forget to set dataSource and delegate for table
table.dataSource = self
table.delegate = self
// Set automatic dimensions for row height
table.rowHeight = UITableViewAutomaticDimension
table.estimatedRowHeight = UITableViewAutomaticDimension
// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return UITableViewAutomaticDimension
【讨论】:
在我下载图像并配置单元格后,我应该如何保存单元格。我是否使用另一个数组。另外我应该把 UIAutomaticDimension 放在哪里,当我最初尝试时,我发现所有 rowHeights 的大小都与estimatedRowHeight
相同
你必须保存图像而不是单元格,钩住单元格图像的纵横比约束并根据cellForRow中检索到的图像大小(宽度/高度)进行更改
我添加了更新后的 TableViewController 并进行了一些编辑,我添加了一个数组来保存图像并使用 UITableViewAutomaticDimension 来设置 rowHeights 但它仍在加载带有空格的图像并多次加载同一行.我是否正确实施了修改?
在文件中缓存图像,因为当您离开该视图控制器时不必再次下载它们【参考方案2】:
在向其添加值之前,请确保 rowHeights 数组已初始化 例如:
cell.setCellImage(image:image!)
if self.rowHeights == nil rowHeights = [CGFloat]()
self.rowHeights?.insert((cell.imageView?.frame.height)!, at: indexPath.row)
【讨论】:
以上是关于为啥调用 reloadRows 后,heightForRowAt 没有在数组中找到值?的主要内容,如果未能解决你的问题,请参考以下文章
我可以在 micRowAve IndexPath... 中调用 reloadRows At IndexPath... 吗?
自定义 UITableViewCell 中的操作按钮调用的 UITableView reloadRows() 总是落后一步
UITableView - reloadRows 方法创建奇怪的滚动错误
什么 tableView.reloadRows(at: [indexPath], with: .none) 会像这样崩溃?