简体   繁体   中英

Protocol / Delegate - Delegate found nil

I've been racking my mind for days trying to figure this out. I have two view controllers (WorkoutViewController and WorkoutAlertViewController). The WorkoutViewController is a tableView for all workouts created. It has swipe action for edit / delete. This view controller also has a "+" as a bar button to open the WorkoutAlertViewController. Also, on the swipe action edit, the WorkoutAlertViewController opens.

在此处输入图像描述

The WorkoutAlertViewController takes the input from the user and passes the data back to the WorkoutViewController upon pressing the Add button.

在此处输入图像描述

Here is the issue. I have a protocol / delegate that gets the user's input entered into WorkoutAlertViewController and passes the information back to the WorkoutViewController to populate the tableView. This works great, However, when the user wants to edit a workout. I need that workout's information to populate the entries on the WorkoutAlertViewController, No matter what I've tried. the delegate for this protocol always returns nil, Therefore. no data is passed.

Here is necessary code for 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])
    }

}

Here is the code for 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
        
    }
    
}

The app crashes in the editAction when calling:

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

Error: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file. As far as I can figure out, the workoutDelegate is not created (nil).

As always, any guidance is greatly appreciated.

You dont need delegate for forward communication.. you can simply call that function directly

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)

        }

In you other class do

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
        
    }
    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM