Archid
Archid

Reputation: 407

How to use Protocols and Delegates with UINavigationController

I have a Welcome controller as the base. It presents Login or Signup controller modally based on the button the user clicks. Now once user presses login in Login controller, I dismiss the Login Controller and notify Welcome controller that user pressed login. I do this using delegates and protocols.

Problem: Now the issue is that my Signup controller does not have the sign up button. It instead directs the user to a SecondSignup controller and that directs to a ThirdSignup controller - all part of a UINavigationController. How can the sign up button in this ThirdSignup controller notify the Welcome controller that user has pressed signup? To avoid confusion, I have specified the hierarchy below

This is the Hierarchy

protocol SignupDelegate{
      func signupButtonPressed()
}

In ThirdSignUp

class ThirdSignupController {
      var delegate: SignupDelegate!

      @objc func handleSignup{
         delegate.signupButtonPressed()
         self.dismiss()
      }
}

In Welcome Controller

class WelcomeController: SignupDelegate {

      @objc func handleSignupButtonPressed(){
         let signupController = UINavigationController(rootViewController: SignupController())
         self.present(signupController, animated: true)
         // ****
         // **** Where do I set the delegate? I am not referencing ThirdSignupController()****
         // ****
      }

      func signupButtonPressed(){
         print("User has pressed sign up button in ThirdSignupController")
      }      
}
`

Upvotes: 0

Views: 73

Answers (1)

Eilon
Eilon

Reputation: 2982

Simplest solution would simply be to carry on the delegate through all view controllers until the third one.
So define a delegate property in every view controller (SignUp, SecondSignUp and ThirdSignUp), and when presenting the first sign up controller, assign the delegate as the Welcome view controller. e.g.

// WelcomeController.swift
let signupController = UINavigationController(rootViewController: SignupController())
signUpController.delegate = self

And now for both SecondSignUp and ThirdSignUp pass on the delegate before presenting them like so:

nextViewController.delegate = self.delegate

And by the end of this you should have your ThirdSignUp view controller have the delegate set as the Welcome view controller.

On a side note, it's best to use delegates as weak references to avoid retain cycles and memory leaks, especially when using the same reference through multiple controllers, so define your delegate properties like so:

weak var delegate: SignUpDelegate

To allow that, define your protocol as:

protocol SignUpDelegate: AnyObject { ... }

Upvotes: 1

Related Questions