Home > OS >  Coordinator pattern doesn't work inside UIView
Coordinator pattern doesn't work inside UIView

Time:10-14

I have 2 buttons inside a View and I can't understand why the Coordinator Pattern does not work for navigation with ViewControllers, only the print inside the button works, but not the delegate for navigation.

Coordinator.swift

import UIKit

protocol Coordinator {
var childCoordinators: [Coordinator] {get set}
init(navigationController: UINavigationController)
func start() 
}

MainCoordinator.swift

    import UIKit
    
    class MainCoordinator: Coordinator {
        
        var childCoordinators: [Coordinator] = []
        
        unowned var navigationController: UINavigationController
        
        required init(navigationController: UINavigationController) {
            self.navigationController = navigationController
        }
        
        func start() {
         let vc: MonitoringViewController = MonitoringViewController()
            vc.delegate = self
            
            self.navigationController.viewControllers = [vc]
        }
        
    }

extension MainCoordinator: NavigationControllerDelegate {
    
    // go to MonitoringViewController
    func navigateToMonitoringViewController() {
        let monitoringViewController: MonitoringViewController = MonitoringViewController()
        monitoringViewController.delegate = self
        self.navigationController.pushViewController(monitoringViewController, animated: false)
    }
    
    // go to AlertViewController
    func navigateToAlertViewController() {
        let alertViewController: AlertViewController = AlertViewController()
        alertViewController.delegate = self
        self.navigationController.pushViewController(alertViewController, animated: false)
    }

}

MonitoringViewController.swift

import UIKit

class MonitoringViewController: UIViewController {

    @IBOutlet weak var CustomNavigationBar: CustomNavigationBar!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }

}

CustomNavigationBar.swift

import UIKit

public protocol NavigationControllerDelegate: AnyObject {
    func navigateToMonitoringViewController()
    func navigateToAlertViewController()
}

final class CustomNavigationBar: UIView {
    
    public weak var delegate: NavigationControllerDelegate?

    @IBAction func buttonNavBar1(_ sender: UIButton) {
        delegate?.navigateToMonitoringViewController()
    }
    
    @IBAction func buttonNavBar2(_ sender: UIButton) {
        delegate?.navigateToAlertViewController()
        print("PRINT ALERT")
    }
   
}

CodePudding user response:

CustomNavigationBar delegate property was not set. Set it to MonitoringViewController instance in viewDidLoad method and add support for NavigationControllerDelegate members in MonitoringViewController instance.

Property names should be written in Lower Camel Case notation, you should change:

@IBOutlet weak var CustomNavigationBar: CustomNavigationBar!

to

@IBOutlet weak var customNavigationBar: CustomNavigationBar!

  1. Solution Monitor View Controller is middle man between customNavigationBar and can react to delegate actions and create side effects

class MonitoringViewController: UIViewController, NavigationControllerDelegate {

    @IBOutlet weak var customNavigationBar: CustomNavigationBar!
    weak var delegate: NavigationControllerDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        customNavigationBar.delegate = self
    }

    func navigateToMonitoringViewController() {
      delegate?.navigateToMonitoringViewController()
    }

    func navigateToAlertViewController() {
      delegate?.navigateToAlertViewController()
    }

}
  1. Solution Monitor View Controller is middle man between customNavigationBar but can't react to interactions between customNavigationBar and coordinator

class MonitoringViewController: UIViewController {

    @IBOutlet weak var customNavigationBar: CustomNavigationBar!
    weak var delegate: NavigationControllerDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        customNavigationBar.delegate = delegate
    }

}
  1. The same solution as second one but this time MonitoringViewController has computed delegate which removes a need to set relation between coordinator and customNavigationBar in 'viewDidLoad' method

class MonitoringViewController: UIViewController {

    @IBOutlet weak var customNavigationBar: CustomNavigationBar!
    var delegate: NavigationControllerDelegate? {
      get { customNavigationBar.delegate }
      set { customNavigationBar.delegate = newValue }
    }
}
  • Related