Существует ли простой способ удаления указанных c пользовательских ячеек из UITableView? - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь создать пустые ячейки покупателя (пользовательские ячейки) в моем табличном представлении, а затем дать пользователю заполнить имена покупателей. Когда пользователь нажимает кнопку удаления для строки / ячейки, он должен удалить соответствующую строку / ячейку независимо от того, заполнено ли текстовое поле для этой строки или нет. Очевидно, я не получаю желаемого поведения. Например, когда я нажимаю delete Row0 (текстовое поле которого говорит «Покупатель 0») и перезагружается табличное представление, Покупатель 0 все еще там, но вместо этого удаляется одна из пустых ячеек Покупателя в конце.

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
    }

}

Ответы [ 2 ]

2 голосов
/ 20 марта 2020

В вашем коде есть серьезная проблема. Вы не обновляете модель данных, поэтому изменения в ячейках теряются при прокрутке пользователя.

Скорее, вполне target- c -i sh протокол / делегат в Swift Закрытие обратного вызова намного удобнее и эффективнее. Вы можете использовать один обратный вызов как для обновления модели, так и для удаления ячейки.

Замените ячейку 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
}
2 голосов
/ 20 марта 2020

Ваша проблема в этой строке

cell.nameField.text = cell.buyerName

Ячейки повторно используются из пула повторного использования, поэтому вы не можете полагаться на ячейку, содержащую какое-либо конкретное состояние или значение.

Ваш покупатель name должно исходить из массива модели данных.

Что-то вроде

cell.nameField.text = self.potentialBuyers[indexPath.row]

Перезагрузка всего табличного представления немного избыточна, когда вы удалили только одну строку; Просто удалите соответствующую строку.

Вы также можете очистить свой протокол делегирования, чтобы ячейке не приходилось отслеживать 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)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...