我在UIViewController中有一个UITableView,它由动态多个部分以及每个部分中的动态多个单元格/行组成。
我尝试使用动作,闭包,索引路径。等等
我想做的是在自定义UITableViewCell中点击一个UIButton,并删除/删除该行和相应的数据。
当前,当我尝试执行此操作时,可以删除该节中的第一个单元格,但是当我尝试删除该节中的最后一个单元格时,出现崩溃,索引超出范围。似乎UIButton保留了旧的indexPath.row
我尝试为表重新加载Data(),但未能成功解决。
从SO(UIButton action in table view cell)使用此解决方案:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var myTableView: UITableView!
var sections: [String] = []
var items: [[String]] = []
var things: [[String]] = []
var things2: [[String]] = []
override func viewDidLoad() {
super.viewDidLoad()
things = [["A","B","C","D"],["X","Y","Z"],["J","A","A","E","K"]]
things2 = [["Q","W","E","R"], ["G","H","J"]]
items.append(contentsOf: things)
items.append(contentsOf: things2)
let secs: Int = Int.random(in: 1...items.count)
for num in 1...secs {
if num == 1 {
sections.append("My Stuff")
} else {
sections.append("Section \(num)")
}
}
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items[section].count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyCustomTableViewCell
cell.theLabel?.text = items[indexPath.section][indexPath.row]
if indexPath.section == 0 {
cell.deleteButton.isHidden = false
cell.editButton.isHidden = false
cell.deleteButton.addAction {
// This is broken, when the action is added in the closure. It persists the indexPath as it is, not changed even with a reloadData()
self.items[indexPath.section].remove(at: indexPath.row)
self.myTableView.deleteRows(at: [indexPath], with: .fade)
}
cell.editButton.addAction {
print("I'm editing this row")
cell.backgroundColor = UIColor.magenta
}
} else {
cell.deleteButton.isHidden = true
cell.editButton.isHidden = true
}
return cell
}
}
// used from https://stackoverflow.com/questions/28894765/uibutton-action-in-table-view-cell/41374087
extension UIControl {
func addAction(for controlEvents: UIControl.Event = .primaryActionTriggered, action: @escaping () -> ()) {
let sleeve = ClosureSleeve(attachTo: self, closure: action)
addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
}
}
class ClosureSleeve {
let closure: () -> ()
init(attachTo: AnyObject, closure: @escaping () -> ()) {
self.closure = closure
objc_setAssociatedObject(attachTo, "[\(arc4random())]", self,.OBJC_ASSOCIATION_RETAIN)
}
@objc func invoke() {
closure()
}
}
在多个部分中使用它的问题是它保留了原始的indexPath和行。
示例:如果第0节有两项(0,1) 我删除了第0部分的项目0-它按预期工作。 然后,当我点击按钮以删除剩余的单元格时,该单元格是第0节第1项,应该已经重新加载到第0节第0项。它失败了,因为闭包仍然将代码块视为第0节第1项。即使通过reloadData ()封套仍会看到indexPath.section和indexPath.row
的原始分配有人有什么想法吗?
我认为这与保留有关,但说实话,我在画空白。我已经在一两天的调试器中看过这段代码,我很沮丧,需要一些Yoda帮助...