07 - List, the Cancel and Done buttons not work when I Edit Checklist

When I Add Checklist, the Cancel And Done button is ok, I can add Checklist or Cancel.

When I press accessory button to Edit Checklist screen, I can edit Checklist, but the Cancel And Done buttons don’t have any response, I can’t close the screen or save the Checklist.

I debug the codes, I find the delegate? is nil, I don’t know why?

import UIKit

protocol ListDetailViewControllerDelegate: class {
    func listDetailViewControllerDidCancel(
        _ controller: ListDetailViewController)
    func listDetailViewController(_ controller: ListDetailViewController,
                                  didFinishAdding checklist: Checklist)
    func listDetailViewController(_ controller: ListDetailViewController,
                                  didFinishEditing checklist: Checklist)

class ListDetailViewController: UITableViewController, UITextFieldDelegate {
    @IBOutlet weak var doneBarButton: UIBarButtonItem!
    @IBOutlet weak var textField: UITextField!
    weak var delegate: ListDetailViewControllerDelegate?
    var checklistToEdit: Checklist?
    override func viewDidLoad() {
        if let checklist = checklistToEdit {
            title = "Edit Checklist"
            textField.text = checklist.name
            doneBarButton.isEnabled = true
    override func viewWillAppear(_ animated: Bool) {
    @IBAction func cancel() {
    @IBAction func done() {
        if let checklist = checklistToEdit {
            // edit
            checklist.name = textField.text!
                                               didFinishEditing: checklist)
        } else {
            let checklist = Checklist(name: textField.text!)
            delegate?.listDetailViewController(self,didFinishAdding: checklist)
    override func tableView(_ tableView: UITableView,willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        return nil
    func textField(_ textField: UITextField,
                   shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {
        let oldText = textField.text! as NSString
        let newText = oldText.replacingCharacters(in: range, with: string)
            as NSString
        doneBarButton.isEnabled = (newText.length > 0)
        return true


    func listDetailViewController(_ controller: ListDetailViewController,
                                  didFinishAdding checklist: Checklist) {
        let newRowIndex = lists.count
        let indexPath = IndexPath(row: newRowIndex, section: 0)
        let indexPaths = [indexPath]
        tableView.insertRows(at: indexPaths, with: .automatic)
        dismiss(animated: true, completion: nil)
    func listDetailViewController(_ controller: ListDetailViewController,
                                  didFinishEditing checklist: Checklist) {
        if let index = lists.index(of: checklist) {
            let indexPath = IndexPath(row: index, section: 0)
            if let cell = tableView.cellForRow(at: indexPath) {
                cell.textLabel!.text = checklist.name
        dismiss(animated: true, completion: nil)

    override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
        let navigationController = storyboard!.instantiateViewController(withIdentifier: "ListDetailNavigationController") as! UINavigationController
        let controller = navigationController.topViewController as! ListDetailViewController
        let checklist = lists[indexPath.row]
        controller.checklistToEdit = checklist
        present(navigationController, animated: true, completion: nil)


It sounds like the delegate isn’t being set in the prepare(for:) segue method. Check that you haven’t missed out the line completely or that the segue identifier literal is exactly the same as use in IB (I always copy/paste them to avoid typos).


1 Like

thank you flanker. I find I miss that

controller.delegate = self

This topic was automatically closed after 166 days. New replies are no longer allowed.