Search code examples
swiftdelegatesprotocols

Swift delegate protocol not calling


I'm a beginner in Swift. I'm trying to use delegate and protocol to send the data backward from a child view to the root view (in navigation controller)

Here is my code:

//FilterViewController.swift:

protocol FilterDelegate: class {
    func finishFilter(query: String);
}

class FilterViewController:BaseViewController,....{
    ....
    weak var delegate : FilterDelegate?

    @IBAction func acceptTapped(_ sender: UIButton) {
        var querystring = ""
        var conditions: [String] = []
        //some logic works with conditions
        querystring = conditions.joined(separator: "&")
        self.delegate?.finishFilter(query: querystring)
        self.navigationController?.popViewController(animated: true)
    }
}

Here is where I call the delegate from Filter

//HouseListController.swift

class HouseListController: BaseViewController,..{
    var filterController = FilterViewController()

    //Here is where I push the FilterViewController
    @IBAction func filterTapped(_ sender: UIButton) {
        self.currentMode = .filter
        self.tracking.previousMode = .filter
        self.filterController = storyboard?.instantiateViewController(withIdentifier: "FilterView") as! FilterViewController
        self.navigationController?.pushViewController(self.filterController, animated: true)
    }

    override func viewDidLoad() {
        self.filterController.delegate = self
    }
}   

extension HouseListController : FilterDelegate {
    func finishFilter(query: String) {
        switch self.currentMode{
        case .normal:
            _ = self.filterHouse(querystring: query , offset: 0, limit: self.tracking.limit).done{ dataHouses in
                self.houses.filter = dataHouses
                self.houses.defaultHouses = dataHouses
                }.done{ _ in
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
            }
        case .search:
            _ = self.filterHouse(searchKey: self.tracking.search.searchKey, querystring: query, offset: 0, limit: self.tracking.limit).done{ dataHouses in
                self.houses.filter = dataHouses
                self.houses.defaultHouses = dataHouses
                }.done{ _ in
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
            }
        default:
            _ = self.filterHouse(querystring: query , offset: 0, limit: self.tracking.limit).done{ dataHouses in
                self.houses.filter = dataHouses
                self.houses.defaultHouses = dataHouses
                }.done{ _ in
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
            }
        }
        self.currentMode = .filter
    }
}

The delegate is not calling to my finishFilter function. Instead, when I pop the view in FilterController, it go straight to viewWillAppear in HouseListController and just stuck there without any calling to the delegate.

Am I missing something?


Solution

  • The code you show in filterTapped is the problem. You create a new instance of FilterViewController from the storyboard but you never set that instance's delegate property.

    I would get rid of your filterController property. Get rid of the line in viewDidLoad that sets its delegate. You never used that code so you have no need for it.

    Then update filterTapped:

    @IBAction func filterTapped(_ sender: UIButton) {
        self.currentMode = .filter
        self.tracking.previousMode = .filter
        let filterController = storyboard?.instantiateViewController(withIdentifier: "FilterView") as! FilterViewController // Update this line
        filterController.delegate = self // Add this line
        self.navigationController?.pushViewController(self.filterController, animated: true)
    }