【问题标题】:How to update data before using a custom TableViewCell button to perform a segue?如何在使用自定义 TableViewCell 按钮执行 segue 之前更新数据?
【发布时间】:2021-05-26 09:34:54
【问题描述】:

目前,我有一个屏幕显示一个带有自定义单元格的 TableView,每个单元格都包含一个 timeButton。当您按下时间按钮时,它会跳到一个弹出屏幕以选择时间。当它被关闭时,它会在主屏幕上更新 timeButton 的标题。

我有一个委托方法,每次按下时都会用按下的 timeButton 的 indexPath.row 更新 rowIndex (实例变量)。我注意到 segue 方法在 rowIndex 被pressedTimeButton(cell: TaskCell) 委托方法更新之前运行。如何在 segue 发生之前让委托方法更新 rowIndex

这是主要的VC代码:

struct Task {
    var name, time: String
}

class MainViewController: UIViewController {

    @IBOutlet weak var taskList: UITableView!
    
    var tasks = [Task]()
    var rowIndex = Int()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set initial task time's value
        tasks.append(Task(name: "", time: "Set time"))
        
        taskList.delegate = self
        taskList.dataSource = self
    }

    // Segue to pop-up screen
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "segueToPopUp" {
            let controller = segue.destination as! PopUpViewController
            
            // ISSUE: rowIndex isn't updated when segue starts
            if tasks[rowIndex].time != "Set time" {    
                // if time is already set, reset time to "0:00"
                tasks[rowIndex].time = "0:00"
            } else {
                // if time is not set 
            } 
    }
    
    // Unwind from pop-up screen
    @IBAction func unwindFromPopUp(_ segue: UIStoryboardSegue) {
        // code to update "timeButton" with selected time
        tasks[rowIndex].time = controller.selectedTaskTime
        ...
    }
}

extension TaskListViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView,
                   numberOfRowsInSection section: Int) -> Int {
        return tasks.count
    }
    
    // Return custom cell + data to show in table view
    func tableView(_ tableView: UITableView,
                   cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell", for: indexPath) as! TaskCell
        cell.delegate = self

        // Configure timeButton in taskCell
        let task = tasks[indexPath.row]
        cell.timeButton.setTitle(task.time, for: .normal)

        return cell
    }
}

extension TaskListViewController: TaskCellDelegate {
    // ISSUE: rowIndex updates after segue method instead of before 
    func pressedTimeButton(onCell cell: TaskCell) {
        if let indexPath = taskList.indexPath(for: cell) {
            rowIndex = indexPath.row        
        }
    }
}

这是我的自定义单元格的代码 + 它的委托协议:

protocol TaskCellDelegate: class {
    func pressedTimeButton(onCell cell: TaskCell)
}

class TaskCell: UITableViewCell, UITextFieldDelegate {
    weak var delegate: TaskCellDelegate?
    
    @IBOutlet weak var timeButton: UIButton!

    override func prepareForReuse() {
        super.prepareForReuse()
        delegate = nil
    }
    
    @IBAction func tapTimeButton(_ sender: UIButton) {
        delegate?.pressedTimeButton(onCell: self)
    }
}

【问题讨论】:

  • 似乎您已在情节提要上将 tableView 单元格中的 segue 设置为 PopUpViewController ,它的作用是在点击单元格后立即触发 segue,而不是将 segue 从 ViewController 拖动到 PopUpViewController 即仅当您调用self.performSegue(withIdentifier: "segueToPopUp", sender: nil) 时才会执行方式segue 也实现func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 此方法将在点击单元格时触发,执行您的任务时间更新然后调用self.performSegue(withIdentifier: "segueToPopUp", sender: nil)

标签: ios swift uitableview delegates


【解决方案1】:

似乎您已在情节提要中将 segue 从 tableView 单元格/timeButton 设置为 PopUpViewController,它的作用是在点击单元格/timeButton 时立即触发 segue,而不是将 segue 从 ViewController 拖动到 PopUpViewController这样segue只会在你调用self.performSegue(withIdentifier: "segueToPopUp", sender: nil)时执行

同时实现func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)(如果你想在点击单元格时执行segue)这个方法将在点击单元格时触发,执行你的任务时间更新。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        rowIndex = indexPath.row      
        self.performSegue(withIdentifier: "segueToPopUp", sender: nil)
}

如果您不想在单元格点击时继续,而只需要按时间按钮点击您现有的pressedTimeButton 方法现在应该可以正常工作

extension TaskListViewController: TaskCellDelegate {
      func pressedTimeButton(onCell cell: TaskCell) {
        if let indexPath = taskList.indexPath(for: cell) {
            rowIndex = indexPath.row
            self.performSegue(withIdentifier: "segueToPopUp", sender: nil)
        }
    }
}

【讨论】:

  • 是的,在我调整了触发 segue 的位置后,segue on time 按钮点击最终完美运行,感谢 Sandeep 的建议!
  • 很高兴能帮上忙 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多