2

I cannot get my delegate protocol to work. I used this stack overflow questions as a guide dispatch event to parent ViewController in swift . I don't know if things have changed in Swift 3 since this post, but my function in my parentViewController is never getting called. Here is my setup.

//PROTOCOL 

protocol PDPPropDetailsDelegate {
func buttonPressed(PropDetailsVC: propertyDetailsVC)

}

// CHILD VIEW CONTROLLER

class propertyDetailsVC: UIViewController {

  var delegate: PDPPropDetailsDelegate?

  @IBAction func emailButton(_ sender: AnyObject) {
    self.delegate?.buttonPressed(PropDetailsVC: self)
}

}

The Button is getting called in Child View Controller.

// PARENT VIEW CONTROLLER

class ImageDetailsVC: UIViewController, PDPPropDetailsDelegate {

   override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "container"{

        container = segue.destination as! ContainerViewController

    }
 }

  @IBAction func segmentControlAct(_ sender: Any) {

    switch segmentControllerView.selectedIndex  {
    case 0: print("case 1")
    container!.segueIdentifierReceivedFromParent("first")

    case 1: print("case 2")
    container!.segueIdentifierReceivedFromParent("second")
     PropertyDetailsVC.delegate = self   // **WHERE I SET DELEGATE**     
        setUpPropertyDetailsUI(property: filterImages)


    default: print("default")
    }

  }

   func buttonPressed(PropDetailsVC: propertyDetailsVC) {
    print("BUTTON PRESSED")
  }
}

Button Pressed is never called. I assume it has to do with the delegate not getting set properly. Not exactly sure why that would be the case though. My setUpPropertyDetailsUI(property: filterImages) takes the Outlets from that VC and sets that works just fine. I did a breakpoint and it is called when I segment over to the PropertyDetailsVC. Any advice or suggestions?

 import UIKit

 open class ContainerViewController: UIViewController {
 //Manipulating container views
 fileprivate weak var viewController : UIViewController!
//Keeping track of containerViews
fileprivate var containerViewObjects = Dictionary<String,UIViewController>()

/** Specifies which ever container view is on the front */
open var currentViewController : UIViewController{
    get {
        return self.viewController

    }
}


fileprivate var segueIdentifier : String!

/*Identifier For First Container SubView*/
@IBInspectable internal var firstLinkedSubView : String!


override open func viewDidLoad() {
    super.viewDidLoad()



}
open override func viewDidAppear(_ animated: Bool) {
    if let identifier = firstLinkedSubView{
        segueIdentifierReceivedFromParent(identifier)
    }
}
override open func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func segueIdentifierReceivedFromParent(_ identifier: String){



    self.segueIdentifier = identifier
    self.performSegue(withIdentifier: self.segueIdentifier, sender: nil)



}




override open func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == segueIdentifier{


        //Remove Container View
        if viewController != nil{


            viewController.view.removeFromSuperview()
            viewController = nil



        }
        //Add to dictionary if isn't already there
        if ((self.containerViewObjects[self.segueIdentifier] == nil)){
            viewController = segue.destination
            self.containerViewObjects[self.segueIdentifier] = viewController

        }else{
            for (key, value) in self.containerViewObjects{

                if key == self.segueIdentifier{

                    viewController = value


                }

            }


        }

        self.addChildViewController(viewController)
        viewController.view.frame = CGRect(x: 0,y: 0, width: self.view.frame.width,height: self.view.frame.height)
        self.view.addSubview(viewController.view)
        viewController.didMove(toParentViewController: self)


    }

}


}


import UIKit

class EmptySegue: UIStoryboardSegue{

override func perform() {

}

/*
 // MARK: - Navigation

 // In a storyboard-based application, you will often want to do a little preparation before navigation
 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
 // Get the new view controller using segue.destinationViewController.
 // Pass the selected object to the new view controller.
 }
 */

 }
bradford gray
  • 537
  • 2
  • 5
  • 18
  • Why don't you add a line to your `emailButton` function that prints our your delegate to see if it's set: `print(self.delegate)` – toddg Aug 10 '17 at 16:08

1 Answers1

1

You seem to be a little confused at the flow of the app. Here's an answer I wrote for someone else's question about this same topic:

https://stackoverflow.com/a/45312362/3832646

Your protocol and Child view controller look great, but there are quite a few things amiss with the rest of your code here:

your prepare(for segue:_, sender:_) is typically where you would set the delegate for the destination (child) view controller.

PropertyDetailsVC.delegate = self won't do anything - you need an instance of the view controller to set its delegate.

It looks like you're using some sort of container global variable that I'm not sure what it would be for.

Take a look at the answer I posted and have another go. It's in Swift 3.

Zig
  • 2,603
  • 1
  • 14
  • 20