Swiftのテーブルビューはスクロールする際にセルを再利用する。
そのため、テーブルビューのセル内にUIButtonを設定している場合、
スクロールするとUIButtonのTagとindexPath.rowと整合性が合わなくなってしまう問題に直面した。
よくあるセル内にUIButtonを設定するコードでは、
タップしたセル内のUIButtonのindexPath.rowとsender.tagが合わない
// Cellの内容
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
// UIButton
let button = UIButton()
button.tag = indexPath.row
// 押下時動作
button.addTarget(self, action: #selector(buttonAction), for: UIControl.Event.touchUpInside)
cell?.addSubview(button)
return cell!
}
@objc func buttonAction(_ sender: UIButton) {
print("buttonTag", sender.tag)
}
以下のコードではセル内のUIButtonのindexPath.rowが正確に取得できる。
sender.tagは使用していない。
@objc func buttonAction(_ sender: UIButton) {
var superview = sender.superview
while let view = superview, !(view is UITableViewCell) {
superview = view.superview
}
guard let cell = superview as? UITableViewCell else {
print("button is not contained in a table view cell")
return
}
guard let indexPath = tableView.indexPath(for: cell) else {
print("failed to get index path for cell containing button")
return
}
print("button is in row \(indexPath.row)")
}
参考サイト
indexpath row after a press button in a table view cell