Tom el Safadi
Tom el Safadi

Reputation: 6796

How do I update elements of the parent view/viewController from a ContainerView?

I have a ViewController, which holds a ContainerView. So therefore I added a class for the ViewController() and a class for the ContainerViews ViewController(). To Illustrate it in better, I have attaced a photo of my storboard scene: enter image description here

When I click the button inside the ContainerView I want to update the Label with a different text, how do I achieve this? IMPORTANT: The ContainerViews button is an IBAction in a seperate ViewController and I want to update the IBOutlet in the seperate ViewController() class. Thanks very much for help!!!

Upvotes: 4

Views: 3357

Answers (1)

nPn
nPn

Reputation: 16758

Getting the parent view controller in the container view and casting it to the type of your parent controller (as mentioned in thefredelement's comment) will work, however it has some drawbacks.

  1. Your container view should really be a view that just happens to be a MVC itself. As a view, it should not know who is controlling it, It might however know that it has a delegate that it can send messages to. For example does a UITextView know that it is a child of a particular class of view controller? No, but it knows it might have a delegate that it can send messages to.
  2. You can't reuse this view controller as a child of any other view controller since it is tightly coupled to the parent class
  3. By simply casting the received parent to type of your parent you are bypassing the type checking.

So the "quick fix" might be to do as suggested in the comment, however, I am providing this answer as a suggestion as how I think in the long run this should be handled. Hopefully others find it useful. I know for me going through the thought process was helpful.

Ideally I think you should declare a variable in the ContainerViewController that either is the Class of your parent view controller, or even better a protocol that your parent controller will conform to. Then in the prepare for segue of the parent view controller you would set this variable.

At the same time your parent should (or at least can) have a variable declared as being of the type of your container view or another protocol which the container will conform to. Then also in the prepare for segue of the parent, get a handle for the Container view controller and store it in the variable you declared.

So something like this:

In your ContainerViewController

var myContainerViewDelegate: ParentViewControllerOrProtocol

In your parent view controller

weak var myChildViewOutlet:  ChildViewControllerOrProtocol

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  if segue.identifier == "embededSegueToChild" {
    if let dvc = segue.destinationViewController.contentViewController as?  ChildViewControllerOrProtocol {
      dvc.myContainerViewDelegate = self
      myChildViewOutlet = dvc
    }
  }

This way your ContainerViewController looks like view object (which I think is what it is supposed consider to be), and the myChildViewOutlet variable is your outlet to that view (which probably should be weak).

The myContainerViewDelegate reference in the Container essentially sets up your parent as the delegate for the container view controller.

now both view controllers have a handle for each other

Upvotes: 2

Related Questions