【问题标题】:Protocol / Delegate - Delegate found nil协议/代表 - 发现代表为零
【发布时间】:2020-07-26 20:13:14
【问题描述】:

几天来我一直在绞尽脑汁想弄清楚这一点。我有两个视图控制器(WorkoutViewController 和 WorkoutAlertViewController)。 WorkoutViewController 是创建的所有锻炼的 tableView。它具有用于编辑/删除的滑动操作。此视图控制器还有一个“+”作为条形按钮来打开 WorkoutAlertViewController。此外,在滑动操作编辑时,WorkoutAlertViewController 会打开。

WorkoutAlertViewController 接收用户的输入,并在按下 Add 按钮时将数据传回 WorkoutViewController。

这就是问题所在。我有一个协议/委托,它将用户输入输入 WorkoutAlertViewController 并将信息传递回 WorkoutViewController 以填充 tableView。这很好用!但是,当用户想要编辑锻炼时,我需要该锻​​炼的信息来填充 WorkoutAlertViewController 上的条目。无论我尝试了什么,这个协议的委托总是返回 nil。因此,不会传递任何数据。

这是 WorkoutViewController 的必要代码:

protocol PassExistingWorkout {
    func didTapEdit(workout: Workout)
}

class WorkoutViewController: UIViewController {

    var workoutDelegate: PassExistingWorkout!

    @IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
                                
        let alertVC = storyboard!.instantiateViewController(withIdentifier: "WorkoutVC") as! WorkoutAlertViewController
        
        alertVC.alertDelegate = self
        
        present(alertVC, animated: true, completion: nil)
                
    }
}

extension WorkoutViewController: PassNewWorkout {

    func didTapAdd(name: String, time: String, date: Date) {
        workoutName = name
        averageTime = time
        creationDate = date
        
        let newWorkout = Workout()
        newWorkout.name = workoutName
        newWorkout.dateCreated = creationDate
        newWorkout.time = averageTime
        
        saveWorkout(workout: newWorkout)

    }
}

    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
            let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { (action, view, actionPerformed) in
            
            if let _ = tableView.cellForRow(at: indexPath){
                
                do {
                    try self.realm.write {
                        self.realm.delete(self.workoutItems![indexPath.row])
                    }
                } catch {
                    print("Error saving category \(error)")
                }
            }
            tableView.reloadData()
        }
        deleteAction.backgroundColor = .red
        
        let editAction = UIContextualAction(style: .normal, title: "Edit") { (action, view, actionPerformed) in
            
            let alertVC = self.storyboard!.instantiateViewController(identifier: "WorkoutVC") as! WorkoutAlertViewController
            
            self.present(alertVC, animated: true, completion: nil)
            
                if let _ = tableView.cellForRow(at: indexPath){
                    
                    self.passedWorkout = self.workoutItems![indexPath.row]
                    self.workoutDelegate.didTapEdit(workout: self.passedWorkout)

                }

        }
    
        editAction.backgroundColor = .gray
        
        return UISwipeActionsConfiguration(actions: [deleteAction, editAction])
    }

}

这是 WorkoutAlertViewController 的代码:

protocol PassNewWorkout {
    func didTapAdd(name: String, time: String, date: Date)
}

class WorkoutAlertViewController: UIViewController {

    var alertDelegate: PassNewWorkout!

    @IBAction func addButtonPressed(_ sender: UIButton) {
        
        dismiss(animated: true, completion: nil)
                
        workoutName = workoutTextField.text!
        creationDate = datePicker.date
        averageTime = timeTextField.text!
        
        alertDelegate.didTapAdd(name: workoutName, time: averageTime, date: creationDate)
        
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let workoutVC = storyboard!.instantiateViewController(identifier: "Main") as! WorkoutViewController
        
        workoutVC.workoutDelegate = self
        
}

extension WorkoutAlertViewController: PassExistingWorkout {

    func didTapEdit(workout: Workout) {
        receivedWorkout = workout
        
    }
    
}

app在editAction调用时崩溃:

  self.workoutDelegate.didTapEdit(workout: self.passedWorkout)

错误:致命错误:在隐式展开可选值时意外发现 nil:文件。据我所知,没有创建锻炼代理(nil)。

一如既往,非常感谢任何指导。

【问题讨论】:

    标签: ios swift delegates protocols


    【解决方案1】:

    您不需要委托进行前向通信..您可以直接调用该函数

    let editAction = UIContextualAction(style: .normal, title: "Edit") { (action, view, actionPerformed) in
                
                let alertVC = self.storyboard!.instantiateViewController(identifier: "WorkoutVC") as! WorkoutAlertViewController
                 self.passedWorkout = self.workoutItems![indexPath.row]
                 alertVC.didTapEdit(workout: self.passedWorkout)
                self.present(alertVC, animated: true, completion: nil)
    
            }
    

    在你其他班级做

    class WorkoutAlertViewController: UIViewController {
    
        var alertDelegate: PassNewWorkout!
    
        @IBAction func addButtonPressed(_ sender: UIButton) {
            
            dismiss(animated: true, completion: nil)
                    
            workoutName = workoutTextField.text!
            creationDate = datePicker.date
            averageTime = timeTextField.text!
            
            alertDelegate.didTapAdd(name: workoutName, time: averageTime, date: creationDate)
            
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            
           }
    
        func didTapEdit(workout: Workout) {
            receivedWorkout = workout
            
        }
        
    }
    

    【讨论】:

    • alertVC 是没有 didTapEdit(workout: Workout) 的 WorkoutAlertViewController。该协议位于 WorkoutViewController 中,以便捕获从中选择的锻炼。然后,我需要在 WorkoutAlertViewController 中使用它。按照我的设置方式,在 WorkoutAlertViewController 中的 viewDidLoad 之前,不会创建 didTapEdit 的委托。为时已晚,这就是我收到 nil 错误的原因。不完全确定如何在 VC 之间进行锻炼。
    • 您不需要协议...只需在您的控制器中编写此方法定义并完成...它将被调用...
    • 做到了!谢谢
    • 有什么问题吗?
    • 这个问题不会导致任何问题,但现在编辑 tableView.reloadData() 崩溃了。我会为此发布另一个问题。再次感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-01
    • 1970-01-01
    相关资源
    最近更新 更多