我有一个UITableView
,用于显示自定义对象的数组。每个对象都有几个属性,包括一个布尔属性,该布尔属性指示此项是否为新项目。
我的UITableViewCell
内容视图在情节提要中定义,并具有类似于以下内容的初始布局:
在UITableViewController
中,当我使单元出队时,我在UITableViewCell
上调用一个方法,该方法将数据配置为在单元中显示,然后再返回。我检查的属性之一是前面提到的.isNew属性。如果该值为true,那么我将创建一个UIButton
并将其作为子视图插入到单元格的内容视图中,因此最终得到这样的结果:
仅出于上下文考虑,此按钮将显示“新”图像以指示该项目是新的。我还连接了一种在点击按钮时将触发的方法。该方法也在我的UITableViewCell
中定义,如下所示:
@objc func newIndicatorButtonTapped(sender: UIButton!) {
// call delegate method and pass this cell as the argument
delegate?.newIndicatorButtonTapped(cell: self)
}
我还创建了一个定义委托方法的协议。我的UITableViewController
符合此要求,当我点击单元格中的按钮时,我看到该代码触发。这是委托方法(在我的UITableViewController
的扩展名中定义):
func newIndicatorButtonTapped(cell: UITableViewCell) {
if let indexPath = self.tableView.indexPath(for: cell) {
print(indexPath.row)
}
}
当我点击单元格时,我看到indexPath
中的行在Xcode中正确打印。当用户点击此按钮时,我需要将其删除(该按钮)并更新UILabel
的约束,以使其再次与内容视图的前沿对齐,如上面的第一个模型所示。不幸的是,我似乎遇到了单元回收的问题,因为UIButton
在滚动浏览不同的单元格时消失并重新出现。我是否需要在回收之前重新设置电池的布局/外观,还是对电池回收的工作方式误解了?任何提示将不胜感激!
答案 0 :(得分:1)
您可能在想的是,您获得了一个“新”单元格,但是当一个单元格被回收时,这意味着它被 重新使用 。
通过更改基本单元格的文本颜色,您可以很容易地看到这一点。
例如:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyID", for: indexPath) as! MyCustomCell
if indexPath.row == 3 {
cell.theLabel.textColor = .red
}
return cell
}
如您所料,当表第一次加载时,第4行的文本颜色将更改(行索引从零开始)。
但是,假设您有100行?滚动时,单元格将被重用 ...,并且每当原始第4个单元格被重用时,它仍将带有红色文本。
因此,正如您所猜测的,是的……您需要在每次使用它时将其单元格“重置”为其原始布局/内容/颜色/等:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyID", for: indexPath) as! MyCustomCell
if indexPath.row == 3 {
cell.theLabel.textColor = .red
} else {
cell.theLabel.textColor = .black
}
return cell
}
答案 1 :(得分:1)
您可能希望考虑隐藏按钮,然后在单击按钮时更改布局。
使用协议将操作从单元格移至tableView,然后在单元格重用时重置布局是一种好方法
在完全编程的单元格中执行以下操作:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! Cell
cell.isNew = indexPath.row == 0 ? true : false
cell.layoutIfNeeded()
return cell
}
单元格类需要类似于:(您可以通过更改“自动布局”约束,直接操作框架或使用UIStackView来执行所需的操作)
class Cell: UITableViewCell {
var isNew: Bool = false {
didSet {
if isNew {
button.isHidden = true
leftConstraint.constant = 20
} else {
button.isHidden = false
leftConstraint.constant = 100
}
self.setNeedsLayout()
}
}
var button: UIButton!
var label: UILabel!
var leftConstraint: NSLayoutConstraint!
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
button = UIButton(type: .system)
button.setTitle("Click", for: .normal)
self.contentView.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.widthAnchor.constraint(equalToConstant: 50).isActive = true
button.heightAnchor.constraint(equalToConstant: 10).isActive = true
button.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 20).isActive = true
button.topAnchor.constraint(equalTo: self.topAnchor, constant: 20).isActive = true
label = UILabel()
label.text = "Label"
self.contentView.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.widthAnchor.constraint(equalToConstant: 200).isActive = true
label.heightAnchor.constraint(equalToConstant: 20).isActive = true
label.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
leftConstraint = label.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 100)
leftConstraint.isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}