dequeueReusableCellWithIdentifier 创建一个新单元格而不是重复使用一个单元格
dequeueReusableCellWithIdentifier creating a new cell instead of reusing one
我在带有自定义单元格的 UIViewController
中使用了 UITableView
。但是,当调用 dequeueReusableCellWithIdentifier
时,它有时会创建一个新单元格而不是重复使用现有单元格。
例如:当第一个单元格第一次更新时,将创建一个新单元格而不是重新使用原始单元格。
我创建了一个图表来帮助更好地说明问题。每个绿色矩形是一个应该发生的动作,每个红色矩形是一个不应该发生的动作。每个箭头都是 dequeueReusableCellWithIdentifier
.
的调用
点击UIButton
时有问题(多次调用该动作),而使用"swipe to delete"动作时,已滑动的单元格可以被新的第二个单元格覆盖,这使得删除按钮看起来像是随机消失。
我该如何解决这个问题?
编辑:
代码自定义单元格
class TableViewCell : UITableViewCell{
@IBOutlet weak var buttonStop: UIButton!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
print("newCell")
backgroundColor = color
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
override func prepareForReuse() {
super.prepareForReuse()
}
var color = UIColor().randomColor()
}
扩展随机颜色的代码
extension UIColor {
func randomColor() -> UIColor {
let aRedValue = CGFloat(arc4random()) % 255 / 255
let aGreenValue = CGFloat(arc4random()) % 255 / 255
let aBlueValue = CGFloat(arc4random()) % 255 / 255
return UIColor(red: aRedValue, green: aGreenValue, blue: aBlueValue, alpha: 1)
}
cellForRow 代码
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell",forIndexPath: indexPath) as! TableViewCell
cell.buttonStop.tag = indexPath.row
cell.buttonStop.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
按钮动作:
func buttonAction(sender: UIButton) {
print("action for cell : \(sender.tag)")
}
我将代码减少到最大值,进一步调查后发现按钮打印了相同的文本,因为我的一个错误我写了两次消息 ^^'
所以剩下的唯一问题是 "swipe to delete" 手势
如果我理解正确的话,您在将操作(的结果)与 tableView 中显示的内容保持同步时遇到了问题。
-
- 了解 UITableView 如何使用单元格:它会询问 UITableViewCell 的数据源。您可以每次都创建一个,也可以向 tableView 索取一个以供重复使用。由于这种机制,您创建的单元格可以先出现在某个位置,然后再出现在另一个位置。
-
- 确保您的逻辑和数据始终独立于实际的 tableViewCells。所以你应该能够只用一个 NSIndexPath 来做你必须做的事情。
-
- UITableViewCell 可以通过以下两种方法之一为您提供 tableViewCell 的有效索引路径
-indexPathForCell:
或 indexPathForRowAtPoint:
.
UITableViewCells的动作处理方式如下:
-
- 创建 UITableViewCell
的自定义子class
-
- 在此子class中创建协议(例如
MyCellDelegate
)
-
- 给这个 class 一个类型为
id <MyCellDelegte>
的 属性 delegate
-
- 在您的数据源中创建单元格时,将此数据源签名为该单元格的委托。
-
- 让这个 subclass 通过在它的委托(委托是你的数据源)上调用协议中的方法来处理操作(滑动/点击)。
-
- 在该委托方法的实现中(在您的数据源上),您可以调用 UITableView 上的方法之一来获取 indexPath。这是您变得独立于实际 tabelViewCell 的点:使用该 indexPath 获取数据,或执行特定操作。
尽管这对于一件小事来说似乎需要做很多工作,但实际上并没有那么多工作,而且您的代码将更加健壮、更易于遵循且耦合度更低。
我在带有自定义单元格的 UIViewController
中使用了 UITableView
。但是,当调用 dequeueReusableCellWithIdentifier
时,它有时会创建一个新单元格而不是重复使用现有单元格。
例如:当第一个单元格第一次更新时,将创建一个新单元格而不是重新使用原始单元格。
我创建了一个图表来帮助更好地说明问题。每个绿色矩形是一个应该发生的动作,每个红色矩形是一个不应该发生的动作。每个箭头都是 dequeueReusableCellWithIdentifier
.
点击UIButton
时有问题(多次调用该动作),而使用"swipe to delete"动作时,已滑动的单元格可以被新的第二个单元格覆盖,这使得删除按钮看起来像是随机消失。
我该如何解决这个问题?
编辑:
代码自定义单元格
class TableViewCell : UITableViewCell{
@IBOutlet weak var buttonStop: UIButton!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
print("newCell")
backgroundColor = color
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
override func prepareForReuse() {
super.prepareForReuse()
}
var color = UIColor().randomColor()
}
扩展随机颜色的代码
extension UIColor {
func randomColor() -> UIColor {
let aRedValue = CGFloat(arc4random()) % 255 / 255
let aGreenValue = CGFloat(arc4random()) % 255 / 255
let aBlueValue = CGFloat(arc4random()) % 255 / 255
return UIColor(red: aRedValue, green: aGreenValue, blue: aBlueValue, alpha: 1)
}
cellForRow 代码
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell",forIndexPath: indexPath) as! TableViewCell
cell.buttonStop.tag = indexPath.row
cell.buttonStop.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
按钮动作:
func buttonAction(sender: UIButton) {
print("action for cell : \(sender.tag)")
}
我将代码减少到最大值,进一步调查后发现按钮打印了相同的文本,因为我的一个错误我写了两次消息 ^^' 所以剩下的唯一问题是 "swipe to delete" 手势
如果我理解正确的话,您在将操作(的结果)与 tableView 中显示的内容保持同步时遇到了问题。
-
- 了解 UITableView 如何使用单元格:它会询问 UITableViewCell 的数据源。您可以每次都创建一个,也可以向 tableView 索取一个以供重复使用。由于这种机制,您创建的单元格可以先出现在某个位置,然后再出现在另一个位置。
-
- 确保您的逻辑和数据始终独立于实际的 tableViewCells。所以你应该能够只用一个 NSIndexPath 来做你必须做的事情。
-
- UITableViewCell 可以通过以下两种方法之一为您提供 tableViewCell 的有效索引路径
-indexPathForCell:
或indexPathForRowAtPoint:
.
- UITableViewCell 可以通过以下两种方法之一为您提供 tableViewCell 的有效索引路径
UITableViewCells的动作处理方式如下:
-
- 创建 UITableViewCell 的自定义子class
-
- 在此子class中创建协议(例如
MyCellDelegate
)
- 在此子class中创建协议(例如
-
- 给这个 class 一个类型为
id <MyCellDelegte>
的 属性
delegate
- 给这个 class 一个类型为
-
- 在您的数据源中创建单元格时,将此数据源签名为该单元格的委托。
-
- 让这个 subclass 通过在它的委托(委托是你的数据源)上调用协议中的方法来处理操作(滑动/点击)。
-
- 在该委托方法的实现中(在您的数据源上),您可以调用 UITableView 上的方法之一来获取 indexPath。这是您变得独立于实际 tabelViewCell 的点:使用该 indexPath 获取数据,或执行特定操作。
尽管这对于一件小事来说似乎需要做很多工作,但实际上并没有那么多工作,而且您的代码将更加健壮、更易于遵循且耦合度更低。