Passing data in between controllers using coordinator pattern

1.2k Views Asked by At

I am trying to understand the working of the Coordinator Pattern.

Here is my code:

import UIKit
import Foundation

class CheckoutCoordinator: Coordinator, ScheduleDelegate {
    
    var childCoordinator: [Coordinator] = [Coordinator]()
    var navigationController: UINavigationController
    
    init(nav: UINavigationController) {
        self.navigationController = nav
    }
    
    func start()  {
        let ctrl = CheckoutController.initFromStoryboard()
        ctrl.coordinator = self
        self.navigationController.pushViewController(ctrl, animated: true)
    }
    
    func openSchedule()  {
        let ctrl = ScheduleController.initFromStoryboard()
        ctrl.delegate = self
        self.navigationController.pushViewController(ScheduleController.initFromStoryboard(), animated: true)
    }
    
    func didSelectTimings(date: NSDate, timings: NSString, distance: Double) {
        
    }
}

From CheckoutController, I go to ScheduleController, do some work which calls its delegate method. The delegate should update some value in CheckoutController and pop scheduleController. I am unable to find any concrete explanation of above senario and how to implement it "properly".

Note that schedule controller has no navigation forward hence no coordinator class for it.

1

There are 1 best solutions below

0
On BEST ANSWER

I would not handle the delegate logic in the coordinator. Instead I would move it right into your CheckoutController. So when calling the ScheduleController it would look in your coordinator like this:

func openSchedule(delegate: ScheduleDelegate?)  {
    let ctrl = ScheduleController.initFromStoryboard()
    ctrl.delegate = delegate
    navigationController.pushViewController(ScheduleController.initFromStoryboard(), animated: true)
}

And in your CheckoutController, conform to the ScheduleDelegate delegate:

class CheckoutController: ScheduleDelegate {
    func didSelectTimings(date: NSDate, timings: NSString, distance: Double) {
       // Do your staff   
    }
}

Then in your ScheduleController after calling the delegate method, I would call the coordinator to pop the self(in that case the ScheduleController).

delegate?.didSelectTimings(date: yourDate, timings: someTiming, distance: distance)
if let checkoutCoordinator = coordinator as? CheckoutCoordinator {
       checkoutCoordinator.popViewController() 
}

The popping logic can be solely in your viewController, but I like to keep the navigation in the Coordinator only. And in your CheckoutCoordinator, or better in your Coordinator(as this function is pretty general), implement the pop function.

extension Coordinator {
     function popViewController(animated: Bool = true) {
         navigationController?.popViewController(animated: animated)
     }
}