我试图实例化表格视图中的空买方单元格(自定义单元格),然后让用户填充买方名称。当用户按下某行/单元格的删除按钮时,无论是否已填充该行的文本字段,都应删除相应的行/单元格。显然,我没有得到期望的行为。例如,当我按Delete Row0(其文本字段显示“ Buyer 0”)并且重新加载表格视图时,Buyer 0仍然存在,但是最后一个空的Buyer单元之一被删除了。
import UIKit
class EntryAlertViewController: UIViewController {
//Fields/Table
@IBOutlet weak var itemField: UITextField!
@IBOutlet weak var priceField: UITextField!
@IBOutlet weak var tableView: UITableView!
//Visual Components
@IBOutlet weak var mainView: UIView!
@IBOutlet weak var titleView: UIView!
@IBOutlet weak var splitItemButton: UIButton!
@IBOutlet weak var cancelButton: UIButton!
@IBOutlet weak var addItemButton: UIButton!
//Commonly Used Objects/Variables
var potentialBuyers: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
potentialBuyers.append("")
tableView.dataSource = self
tableView.register(UINib(nibName: "BuyerCell", bundle: nil), forCellReuseIdentifier: "ReusableCell")
}
override func viewWillAppear(_ animated: Bool) {
}
@IBAction func splitItemPressed(_ sender: UIButton) {
potentialBuyers.append("")
tableView.reloadData()
}
}
这是tableview数据源和删除按钮委托。
extension EntryAlertViewController: UITableViewDataSource, DeleteButtonDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return potentialBuyers.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! BuyerCell
cell.deleteButtonDelegate = self
cell.indexPath = indexPath
cell.nameField.text = cell.buyerName
if potentialBuyers.count == 1 {
cell.deleteButton.isHidden = true
} else {
cell.deleteButton.isHidden = false
}
return cell
}
func deletePressed(index: Int) {
potentialBuyers.remove(at: index)
tableView.reloadData()
}
}
这是我的BuyerCell类,带有UITextFieldDelegate作为扩展。
import UIKit
protocol DeleteButtonDelegate {
func deletePressed(index: Int)
}
class BuyerCell: UITableViewCell {
@IBOutlet weak var deleteButton: UIButton!
@IBOutlet weak var nameField: UITextField!
var deleteButtonDelegate: DeleteButtonDelegate!
var indexPath: IndexPath!
var buyerName: String?
override func awakeFromNib() {
super.awakeFromNib()
self.nameField.delegate = self
}
@IBAction func deletePressed(_ sender: UIButton) {
//print the indexPath.row that this was pressed for
print("delet pressed for \(indexPath.row)")
self.deleteButtonDelegate?.deletePressed(index: indexPath.row)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension BuyerCell: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
print("textFieldDidBeginEditing")
buyerName = nameField.text
}
func textFieldDidEndEditing(_ textField: UITextField) {
print("textFieldDidEndEditing")
buyerName = nameField.text
}
}
答案 0 :(得分:2)
您的问题出在这行
cell.nameField.text = cell.buyerName
单元格是从重用池中重用的,因此您不能依赖拥有任何特定状态或值的单元格。
您的买家名称必须来自您的数据模型数组。
类似
cell.nameField.text = self.potentialBuyers[indexPath.row]
仅删除一行时,重新加载整个tableview有点过多;只需删除相关行即可。
您还可以清理委派协议,以便该单元无需跟踪其indexPath
-
protocol DeleteButtonDelegate {
func deletePressed(in cell: UITableViewCell)
}
在您的单元格中:
@IBAction func deletePressed(_ sender: UIButton) {
self.deleteButtonDelegate?.deletePressed(in: self)
}
在您的视图控制器中:
func deletePressed(in cell: UITableViewCell) {
guard let indexPath = tableView.indexPath(for: cell) else {
return
}
potentialBuyers.remove(at: indexPath.row)
tableView.deleteRows(at:[indexPath], with: .automatic)
}
答案 1 :(得分:2)
您的代码中存在一个主要问题。您没有更新数据模型,因此当用户滚动时,单元格中的更改会丢失。
在Swift回调闭包中,而不是相当 objective-c-ish 协议/委托更加方便和高效。您可以使用一个回调来更新模型和删除单元格。
用
替换BuyerCell
单元格
class BuyerCell: UITableViewCell {
@IBOutlet weak var deleteButton: UIButton!
@IBOutlet weak var nameField: UITextField!
var callback : ((UITableViewCell, String?) -> Void)?
override func awakeFromNib() {
super.awakeFromNib()
self.nameField.delegate = self
}
@IBAction func deletePressed(_ sender: UIButton) {
callback?(self, nil)
}
}
extension BuyerCell: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
print("textFieldDidBeginEditing")
callback?(self, nameField.text)
}
func textFieldDidEndEditing(_ textField: UITextField) {
print("textFieldDidEndEditing")
callback?(self, nameField.text)
}
}
在cellForRow
中的控制器中分配回调并处理操作。如果对单元格进行重新排序,插入或删除,这些动作也可以可靠地工作。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! BuyerCell
let buyerName = potentialBuyers[indexPath.row]
cell.nameField.text = buyerName
cell.callback = { [unowned self] cCell, cName in
let currentIndexPath = tableView.indexPath(for: cCell)!
if let name = cName {
self.potentialBuyers[currentIndexPath.row] = name
} else {
self.potentialBuyers.remove(at: currentIndexPath.row)
tableView.deleteRows(at: [currentIndexPath], with: .fade)
}
}
cell.deleteButton.isHidden = potentialBuyers.count == 1
return cell
}