'Callback is not working when button tapped

I want to trigger an action on button tap with my callback. Also I have presenter and coordinator. But nothing happenes. My code is not working in this closure:

startViewController.output = { [weak self] action in
            switch action {
            case .registrationButtonTapped:
                self?.showRegistrationViewController()
            case .loginButtonTapped:
                self?.showLoginViewController()
            }
        }

In my ViewController I have enum:

    enum StartViewControllerButton {
     case registrationButtonTapped
     case loginButtonTapped 
}

callback:

var output: ((StartViewControllerButton) -> Void)?

and selectors:

@objc func registrationButtonPressed() {
        startModulPresenter.openNextScreen()
        self.output?(.registrationButtonTapped)
    }

    @objc func loginButtonPressed() {
        startModulPresenter.openNextScreen()
        self.output?(.loginButtonTapped)
    }

My Presenter

class StartModulPresenter: StartModulPresenterProtocol {
    
    var navigationController: UINavigationController
    var coordinator: CoordinatorProtocol?
    
    //Init
    
    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
        
        coordinator = AuthorizationCoordinator(navigationController: navigationController)
    }
    
    //Functions
    
    func openNextScreen() {
        coordinator?.start()
    }
    
}

My Coordinator:

class AuthorizationCoordinator: RegistrationCoordinatorProtocol {
    
    var presenter: PresenterProtocol?
    var navigationController: UINavigationController
    var childCoordinators: [CoordinatorProtocol] = []
    
    //Init
    
    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }
    
    func start() {
        presenter = StartModulPresenter(navigationController: navigationController)
        
        let startViewController = StartViewController(startModulPresenter: presenter as! StartModulPresenter)
        
        startViewController.output = { [weak self] action in
            switch action {
            case .registrationButtonTapped:
                self?.showRegistrationViewController()
            case .loginButtonTapped:
                self?.showLoginViewController()
            }
        }
    }
    
    private func showRegistrationViewController() {
        let registrationViewController = RegistrationViewController()
        registrationViewController.view.backgroundColor = .orange
        self.navigationController.pushViewController(registrationViewController, animated: true)
    }
    
    private func showLoginViewController() {
        let loginViewController = LoginViewController()
        loginViewController.view.backgroundColor = .orange
        self.navigationController.pushViewController(loginViewController, animated: true)
    }
}


Solution 1:[1]

Could you check if startViewController is pushed/presented or not?

    func start() {
        presenter = StartModulPresenter(navigationController: navigationController)
        
        let startViewController = StartViewController(startModulPresenter: presenter as! StartModulPresenter)
        
        startViewController.output = { [weak self] action in
            switch action {
            case .registrationButtonTapped:
                self?.showRegistrationViewController()
            case .loginButtonTapped:
                self?.showLoginViewController()
            }
        }
    }

And, is self.output is nil or not? If it is nil please check your assignment call, it needed to be called before you use this variable.


    @objc func loginButtonPressed() {
        startModulPresenter.openNextScreen()
        self.output?(.loginButtonTapped)
    }

Honestly, I don't recommend you to use this design pattern, just a simple thing but the real result is too complicated. Just use protocol-based MVC. View communicate with Controller via protocol/closure or Reactive-based with Combine (PassthroughSubject/CurrentValueSubject)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Neklas