Search code examples
iosswiftdelegatesprotocolsdelegation

Assign Delegate Without Segue or Programatic Call


I Need VC3 To Be Able to Send VC1 a Function Call!

I understand the basics of delegation and I just read this guide on how to assign a delegate without a prepareForSegue:

Swift Delegate Between Two VCs Without Segue

But what if there's a VC between the two that need to talk? For instance, VC1 presents VC2 which presents VC3. VC3 would like VC1 to do some work. With no segue and the programatic VC3 call happening in VC2, how can I accomplish this?


Solution

  • Well if you want to continue using the delegation pattern, you'll need to update the VC2 to pass throw the delegate callbacks.

    So using the code from that example you posted:

    ViewControllerOne:

    class ViewControllerOne: UIViewController,testProtocol {
    
        @IBAction func btInit(sender: AnyObject) {
            println("Bt Init")
    
            let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let viewController2: ViewControllerTwo = storyBoard.instantiateViewControllerWithIdentifier("viewTarget") as ViewControllerTwo
            viewController2.viewController1 = self
            self.presentViewController(initViewController,animated: false, nil)
    
        }
    
        func testDelegate(){
            println(" in my view controller delegate ")
        }
    
    }
    

    ViewControllerTwo:

    class ViewControllerTwo: UIViewController,testProtocol {
    
        var viewController1: ViewControllerOne? = ViewControllerOne()
    
        @IBAction func btInit(sender: AnyObject) {
            println("Bt Init")
    
            let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let viewController3: ViewControllerThree = storyBoard.instantiateViewControllerWithIdentifier("viewTarget") as ViewControllerThree
            viewController3.delegate = viewController1
            self.presentViewController(initViewController,animated: false, nil)
    
        }
    
    }
    

    ViewControllerThree:

    protocol testProtocol {
        func testDelegate() // this function the first controllers
    }
    
    class ViewControllerThree: UIViewController {
    
        @IBAction func BtTarget(sender: AnyObject) {
    
            println("bt target pressed")
    
            delegate?.testDelegate()
        }
    
        var delegate : testProtocol?
    }
    

    A Better Option

    Personally, I don't like this approach because it adds an unnecessary coupling on ViewControllerTwo from the other two VCs that need to communicate, so IMO a better alternate is to use the Observer pattern through use of NSNotification such that VC1 registers as a listener for a notification, and then at some later point, VC3 posts the notification (and optionally whatever data), VC1 receives it and does whatever it needs to.