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!
- 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()
}
}
- 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
}
}
- 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 }
}
}