由于完成处理程序,单元格高度未正确计算
Posted
技术标签:
【中文标题】由于完成处理程序,单元格高度未正确计算【英文标题】:Cell height not being calculated properly because of Completion Handler 【发布时间】:2016-03-07 14:59:17 【问题描述】:我有一个单元格,其中包含从 Amazon S3 检索的图像。此图像的高度将影响单元格的高度,但不幸的是,在确定单元格高度后,图像会在完成处理程序中检索。如果我向下和向上滚动,单元格会正确重新加载。
滚动前(单元格高度不正确):
滚动后(正确的单元格高度):
单元配置(一些不必要的东西为了可读性而编辑):
func setCompletionCell(completion: CompletionPublic, contentType: String, classType: String)
self.completionPub = completion
self.selectionStyle = UITableViewCellSelectionStyle.None //Disables clicking
//Setting image or video
if (contentType == "image")
nwa.fetchSignedUrl("image/accepted/" + completion.mediaId + ".png") (result, err) in
self.nwa.fetchImage(result) (image, err) in
if image != nil
let screenSize: CGRect = UIScreen.mainScreen().bounds
var multiplyNum = screenSize.width / image.size.width
//if image height is going to be more than 60% of the screen, resize width and height to ensure that it isn't greater than 60% while keeping the aspect ratio correct
if ((image.size.height*multiplyNum) > (screenSize.height*0.6))
multiplyNum = screenSize.height*0.6 / image.size.height
self.imageViewWidthConstraint.constant = (multiplyNum*image.size.width)
self.imageViewHeightConstraint.constant = screenSize.height*0.6
else
self.imageViewWidthConstraint.constant = screenSize.width
self.imageViewHeightConstraint.constant = (multiplyNum*image.size.height)
self.imgView.image = image
else
//no image returned
else if (contentType == "video")
ytplayer.loadWithVideoId(completion.mediaId)
TableView 委托方法:
func callNWT(tableView: UITableView, completionHandler: () -> ())
switch trendingToggle
case 0:
nwt.getTrendingBounties(0) (bountyArr, err) in
//@TODO: change pos
if bountyArr == nil
self.bountyArr = []
else
self.bountyArr = bountyArr as [BountyPublic]
if self.bountyArr.count == 0
completionHandler()
self.reloadTableViewContent(tableView)
case 1:
nwt.getTrendingCompletions(0) (compArr, err) in
if compArr == nil
self.compArr = []
else
self.compArr = compArr as [CompletionPublic]
if self.compArr.count == 0
completionHandler()
self.reloadTableViewContent(tableView)
case 2:
nwt.getTrendingPeople(0) (peopleArr, err) in
if peopleArr == nil
self.peopleArr = []
else
self.peopleArr = peopleArr as [Person]
if self.peopleArr.count == 0
completionHandler()
self.reloadTableViewContent(tableView)
default:
break
func configureTableView(tableView: UITableView)
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 500.0
tableView.allowsSelection = false; //disables selection highlighting of cells
tableView.tableFooterView = UIView()
tableView.dataSource = self
func reloadTableViewContent(tableView: UITableView)
dispatch_async(dispatch_get_main_queue(), () -> Void in
tableView.reloadData()
print("reloading table view content")
tableView.scrollRectToVisible(CGRectMake(0, 0, 1, 1), animated: false)
)
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
if trendingToggle == 0
return bountyArr.count
else if trendingToggle == 1
return compArr.count
else
return peopleArr.count
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
if trendingToggle == 0
return bountyCellAtIndexPath(tableView, indexPath: indexPath)
else if trendingToggle == 1
return completedCellAtIndexPath(tableView, indexPath:indexPath)
else
return personCellAtIndexPath(tableView, indexPath: indexPath)
func completedCellAtIndexPath(tableView: UITableView, indexPath:NSIndexPath) -> CompletedCell
var cell: CompletedCell
if compArr[indexPath.row].contentType == "image"
cell = tableView.dequeueReusableCellWithIdentifier(completedImgCellIdentifier) as! CompletedCell
let comp = compArr[indexPath.row]
cell.setCompletionCell(comp, contentType: "image", classType: "trending")
else //video
cell = tableView.dequeueReusableCellWithIdentifier(completedVidCellIdentifier) as! CompletedCell
let comp = compArr[indexPath.row]
cell.setCompletionCell(comp, contentType: "video", classType: "trending")
return cell
如何确保第一次正确计算单元格高度?有没有办法可以延迟代码执行,直到检索到图像?或者这不是一个好主意?
【问题讨论】:
发布一些代码,您的表格视图委托方法和单元格配置。 你永远不应该暂停主队列来处理网络请求。你应该做的是在设置图像后你必须通知表格视图布局子视图。 你可以在这里找到示例代码***.com/questions/33975355/… 您应该将下载的图像保存在本地,然后使用“在索引路径重新加载行”tableview 委托方法在完成处理程序中重新加载带有图像的单元格。 如果有成百上千张图片怎么办?我还应该在本地下载它们吗? @Nishant 【参考方案1】:在完成处理程序中重新加载表格视图。
tableView.reloadData()
在数据源/委托协议的 heightForRowAtIndex
方法中,使用图像重新计算高度并为每个单独的单元格返回适当的值。
当您调用 reloadData() 时,所有数据源/委托方法都会再次调用,因此返回正确的高度将允许您根据需要调整单元格的大小。
【讨论】:
除非图像在本地保存和检索,否则重新加载 tableview 将不起作用。此外,您可以只重新加载该单元格,而不是一次又一次地重新加载整个表格。 你是对的,整个 tableView 不需要重新加载 - 只是有问题的行,但为什么需要在本地保存图像? (我假设您的意思是在应用程序包中)。为什么不能从服务器检索图像将其存储在数据源委托中的数组中,并调用(无论哪种)您喜欢的 reloadTableView 方法,然后在 heightForRowAtIndex 方法中返回与 indexPath.row 中的 indexPath.row 对应的图像的高度图像数组? 通过本地保存然后调用tableView.reloadData() 解决,不再从S3 获取图像。谢谢@Nishant 和布莱克。 @Mitchell:太好了。我建议您在完成处理程序中使用tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
而不是tableView.reloadData()
。以上是关于由于完成处理程序,单元格高度未正确计算的主要内容,如果未能解决你的问题,请参考以下文章
UITableView动态单元格高度仅在某些滚动后才能正确显示
iOS - 带有 UITextView 的表格视图单元格未正确调整大小