【问题标题】:Passing data from one Custom TableView Cell to another using delegates and protocols使用委托和协议将数据从一个自定义 TableView 单元传递到另一个
【发布时间】:2019-12-06 12:59:05
【问题描述】:

我正在尝试快速了解委托和协议,特别是如何在自定义表格视图单元格之间传递数据。

我已经设置了一个简单的项目来测试它,其中包含三个类、一个 TableViewController 和两个使用 .xib 用于布局的自定义单元格:DateLabelCell 和 DatePickerCell。期望的结果是,当更改日期选择器时,它会使用新值更新日期标签单元格。

目前 DatePicker Cell 正在与 TableViewController 通信,但我似乎无法让 TableViewController 然后与 Datelabel Cell 通信。我认为这与 Datelabel Cell 没有正确引用 tableviewcontroller 有关吗?

非常感谢任何帮助或见解。

干杯,

TableViewController

    import UIKit

protocol DateLabelDelegate: AnyObject {
    func setDateLabel(_ text: String)
}


class TableViewController: UITableViewController {

    weak var dateLabelDelegate: DateLabelDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()

        tableViewSetup()

    }

     func tableViewSetup() {

        // Format tableView
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 200
        tableView.tableFooterView = UIView(frame: CGRect.zero) // Removes Empty Cells
        tableView.separatorStyle = UITableViewCell.SeparatorStyle.none

        // Register Cells
        tableView.register(UINib(nibName: "DatePickerCell", bundle: nil), forCellReuseIdentifier: "DatePickerCell")
        tableView.register(UINib(nibName: "DateLabelCell", bundle: nil), forCellReuseIdentifier: "DateLabelCell")

        }


    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return 2
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        if indexPath.row == 0 {
             let cell = tableView.dequeueReusableCell(withIdentifier: "DateLabelCell", for: indexPath) as! DateLabelCell

             return cell
        } else {
              let cell = tableView.dequeueReusableCell(withIdentifier: "DatePickerCell", for: indexPath) as! DatePickerCell
                cell.dateDelegate = self
              return cell
        }
    }
}

extension TableViewController: DatePickerDelegate {
    func setDate(_ text: String) {
        print("WORKING: TableViewController: DatePickerDelegate")
        dateLabelDelegate?.setDateLabel(text)
    }


}

DatePickerCell

import UIKit

protocol DatePickerDelegate: AnyObject {
    func setDate(_ text: String)
}

class DatePickerCell: UITableViewCell {

    weak var dateDelegate: DatePickerDelegate?

    @IBOutlet var datePicker: UIDatePicker!
    let formatter = DateFormatter()

        override func awakeFromNib() {
            super.awakeFromNib()
             formatter.dateFormat = "dd.MM.yyyy"
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

    override func prepareForReuse() {
    }

    @IBAction func datePickerDidChange(_ sender: Any) {
        let result = formatter.string(from: datePicker.date)
        print("RESULT -> \(result)")
        dateDelegate?.setDate(result)
    }

}

日期标签单元格

import UIKit

class DateLabelCell: UITableViewCell {

    @IBOutlet var dateLabel: UILabel!

    let date = Date()
    let formatter = DateFormatter()
    let sendingTableVC = TableViewController()



    override func awakeFromNib() {
        super.awakeFromNib()

        sendingTableVC.dateLabelDelegate = self

        formatter.dateFormat = "dd.MM.yyyy"

        let result = formatter.string(from: date)
        dateLabel.text = "Date: \(result)"

    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

extension DateLabelCell: DateLabelDelegate {
    func setDateLabel(_ text: String) {
        print("DATE LABEL UPDATED")
        dateLabel.text = text
    }

}

【问题讨论】:

  • 在视图控制器中的 dateLabelDelegate?.setDateLabel(text) 之后,您需要重新加载您的 tableview。

标签: ios swift uitableview delegates swift-protocols


【解决方案1】:

更新 tableview/collectionviewcell 的正确方法是重新加载特定的单元格。并且您应该始终维护代表您的表格视图单元格的数据,因为您的单元格不是持久性和可重用的。您可以在创建单元格时使用该数据填充单元格的属性。

在您的情况下,日期是需要持久化的数据。在这种情况下,您可以简单地将其作为控制器中的一个字段。

import UIKit

class DateLabelCell: UITableViewCell {

    @IBOutlet var dateLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    func setDate(_ text: String) {
        dateLabel.text = text
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
}
class TableViewController: UITableViewController {
    var date: String = "Date"

    .......

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        if indexPath.row == 0 {
             let cell = tableView.dequeueReusableCell(withIdentifier: "DateLabelCell", for: indexPath) as! DateLabelCell
             cell.setDate(self.date)
             return cell
        } else {
              let cell = tableView.dequeueReusableCell(withIdentifier: "DatePickerCell", for: indexPath) as! DatePickerCell
                cell.dateDelegate = self
              return cell
        }
    }

}
extension TableViewController: DatePickerDelegate {
    func setDate(_ text: String) {
        self.date = text
        tableView.reloadRows(at: [IndexPath(item: 0, section: 0)], with: .automatic)
    }
}

【讨论】:

  • 虽然您的答案在技术上是正确的,但在将其作为答案发布之前,请考虑仔细检查您的代码。您的“中间”块在 UITableViewCell 类中显示 cellForRowAt --- 当然,它不应该是。
  • 是的。它应该是 tableViewController。我错过了。谢谢。干杯。
  • 感谢@SubramanianMariappan,这对于不保存数据的单元格非常有意义!干杯
【解决方案2】:

您还可以使用回调,它非常强大且更易于理解:

class TableViewController: UITableViewController {

    //MARK: Properties
    var date = "today"

    .....

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        if indexPath.row == 0 {
             let cell = tableView.dequeueReusableCell(withIdentifier: "DateLabelCell", for: indexPath) as! DateLabelCell
             cell.setDate(self.date)
             return cell
        } else {
             let cell = tableView.dequeueReusableCell(withIdentifier: "DatePickerCell", for: indexPath) as! DatePickerCell
             cell.dateSelectedCallback = { newDate in //here we get the new date
                 self.date = newDate
                 self.tableView.reloadData()
             }
             return cell
        }
    }
}

日期标签单元格

class DateLabelCell: UITableViewCell {

    //MARK: IBOutlets
    @IBOutlet var dateLabel: UILabel!

    //MARK: Cell setup
    func setDate(_ text: String) {
        dateLabel.text = text
    }
}

DatePickerCell

这里我们创建一个可选的回调变量。为什么可选?如果它没有被实施,它不会崩溃。回调就像简单的完成处理程序,您可以通过它们传递任何数据。

class DatePickerCell: UITableViewCell {

    //MARK: IBOutlets
    @IBOutlet var datePicker: UIDatePicker!

    //MARK: Properties
    var dateSelectedCallback: ((_ date: String) -> ())?
    let formatter = DateFormatter()

    //MARK: Lifecycles
    override func awakeFromNib() {
        super.awakeFromNib()
        formatter.dateFormat = "dd.MM.yyyy"
    }

    //MARK: IBActions
    @IBAction func datePickerDidChange(_ sender: Any) {
        let result = formatter.string(from: datePicker.date)
        print("RESULT -> \(result)")
        dateSelectedCallback?(result) //we pass the date string here
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 2020-09-18
    相关资源
    最近更新 更多