【问题标题】:Constraints of views in custom UITableViewCell getting reset on cell reuse自定义 UITableViewCell 中的视图约束在单元重用时重置
【发布时间】:2015-12-08 15:20:10
【问题描述】:

我遇到了在自定义表格单元格中显示 ImageView 的问题。我正在尝试执行以下操作:在 cellForRowAtIndexPath 中,我检查用户 ID 是否与保留对象内的 id 匹配。如果是这样,ImageView(默认隐藏)将在单元格的右侧可见。这一切正常,直到 iOS 开始重用单元格。在重复使用的单元格上,ImageView 始终位于单元格的左侧,而不是右侧(其正常位置)。我试图找出为什么会发生这种情况,但我运气不佳。我将不胜感激。

编辑:看来我遇到了与该用户相同的问题: Custom cell imageView shifts to left side when editing tableView

EDIT2:经过更多调试,我发现每当单元被重用时,它的约束就会改变。首次创建单元格时调用 constraintsAffectingLayoutForAxis(LayoutConstraintsAxis.Horizo​​ntal)

constraintsAffectingLayoutForAxis(LayoutConstraintsAxis.Vertical)
显示两个空数组。这些单元格是通过情节提要制作的,所以我猜我无法使用这些方法读取它们(?)
在细胞被重用并且我再次调用上面的方法之后,它突然有一堆约束。然而,这些约束都是错误的,我认为这是图像视图放错位置的原因。

这是我创建单元后的日志:

Timelabel holds Optional(2) constraints
Horizontal constraints are: Optional([])
Vertical constraints are: Optional([])
ImageView holds Optional(4) constraints
Horizontal constraints are: Optional([])
Vertical constraints are: Optional([])  

这是在我将单元格滚动出视图并返回视图后打印的内容,从而导致它被重用:

Timelabel holds Optional(2) constraints
Horizontal constraints are: Optional([<NSLayoutConstraint:0x15d02a60      H:|-(38)-[UILabel:0x15f68500]   (Names: '|':UITableViewCellContentView:0x15f7de60 )>, <NSContentSizeLayoutConstraint:0x15f4e3f0 H:[UILabel:0x15f68500(103)] Hug:251 CompressionResistance:750>])
Vertical constraints are: Optional([<NSLayoutConstraint:0x15f69600 V:|-(2)-[UILabel:0x15f68500]   (Names: '|':UITableViewCellContentView:0x15f7de60 )>, <NSContentSizeLayoutConstraint:0x15f76d10 V:[UILabel:0x15f68500(21)] Hug:251 CompressionResistance:750>])
ImageView holds Optional(4) constraints
Horizontal constraints are: Optional([<NSLayoutConstraint:0x15d18390 H:[UIImageView:0x15f64260(47)]>, <NSLayoutConstraint:0x15f7c900 H:[UIImageView:0x15f64260]-(29)-|   (Names: '|':UITableViewCellContentView:0x15f7de60 )>, <NSAutoresizingMaskLayoutConstraint:0x15f77b90 h=--& v=--& H:[UITableViewCellContentView:0x15f7de60(280)]>])
Vertical constraints are: Optional([<NSLayoutConstraint:0x15db4570 V:|-(0)-[UIImageView:0x15f64260]   (Names: '|':UITableViewCellContentView:0x15f7de60 )>, <NSLayoutConstraint:0x15f736e0 V:[UIImageView:0x15f64260(48)]>])

我的 cellForRowAtIndexPath 方法:

func tableView(tableview: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
    let cellIdentifier = "ReservationCell"

    let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? ReservationCell
    let res: Reservation = reservationArray[indexPath.row]
    let startTime = DateUtils.parseUTCDateTimeStringToTimeString(res.start)
    let endTime = DateUtils.parseUTCDateTimeStringToTimeString(res.end)
    cell!.delegate = self
    let storedUserID = ELabAccount.getUserID()
    let reservationUserID = String(res.reservedForId)
    //Check if reservation belongs to currently logged in user
    if(storedUserID == reservationUserID){
        let buttons = NSMutableArray()
        buttons.sw_addUtilityButtonWithColor(UIColor.lightGrayColor(), title: LocalizedString("edit"))
        buttons.sw_addUtilityButtonWithColor(UIColor.redColor(), title: LocalizedString("delete"))
        cell!.rightUtilityButtons = buttons as [AnyObject]
        cell!.imageView!.hidden = false
        cell!.backgroundColor = UIColor(red:0.42, green:0.64, blue:0.76, alpha:1.0)
    }else{
        cell!.backgroundColor = UIColor(red:1.00, green:0.55, blue:0.25, alpha:1.0)
    }
    cell!.timeLabel.text = startTime + " - " + endTime
    cell!.nameLabel.text = res.reservedForName

    return cell!
}

【问题讨论】:

  • " 总是在左侧结束",你是什么意思?它总是出现?
  • 我的意思是当 ImageView 可见时,它会显示在左侧而不是右侧。
  • 如果单元格被回收,它将重新使用现有的单元格。因此,如果您有 if/else 部分,您应该在 if AND else 中处理相同的 ui 更改。 cell!.imageView!.hidden = false 仅在“if”中完成。很可能你错过了 cell!.imageView!.hidden = true in "else"
  • @JörnBuitink imageview 默认是隐藏的。它只显示通过 if 语句的单元格。我的问题不是 ImageView 出现在错误的单元格上,而是它出现在错误的一侧(也就是单元格的左侧)。就好像 ImageView 的约束突然消失了一样。
  • 显示您取消隐藏图像视图的位置 - 它不在您发布的代码中。

标签: ios swift uitableview constraints


【解决方案1】:

好吧,我设法找到了解决方法。我最终做的是在我的自定义表格单元格的内容视图上将 translateAutoresizingMaskIntoConstraints 标志设置为 false。这导致 imageView 在单元重用后不再移动,但它确实将每个子视图向下移动,以便它们只有一半可见。使用 Storyboard 添加一些额外的约束来解决这个问题。

【讨论】:

  • 引人入胜的答案。谢谢你分享这个。我很想对任何一位 iOS 开发者进行猴子攻击。
  • @Trip 让我知道你是否愿意这样做,我会为你保留它们 :)
【解决方案2】:

always ends up on the left side 不是很清楚,但我猜你面临一个正在发生的问题:当你开始重用单元格时,图像出现在理论上不应该出现的位置。

这是因为imageview在ID匹配时显示,但在ID不匹配时不隐藏。因此,通过重用之前ID匹配成功的单元格,将显示图像。

如果匹配失败,只需隐藏图像视图:

if(storedUserID == reservationUserID){
       ....
} else{
    // hides the image view
    cell!.imageView!.hidden = true
    cell!.backgroundColor = UIColor(red:1.00, green:0.55, blue:0.25, alpha:1.0)
}

【讨论】:

  • 我重新表述了这个问题,因为人们已经表达了他们对它的困惑。以防万一,我会尝试再次解释它:通常,当 if 语句返回 true 时,ImageView 变为可见并且应该显示在右侧。当单元格被重用时,由于某种原因,ImageView 最终位于左侧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
  • 2015-11-04
  • 2020-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多