4

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!!!

nPn
  • 16,254
  • 9
  • 35
  • 58
Tom el Safadi
  • 6,164
  • 5
  • 49
  • 102
  • IIRC I think you can access the "parent" via the parent view controller property of the view controller within the container. If not, check out NSNotificationCenter or creating a delegate. – Fred Faust Nov 04 '15 at 02:18
  • Yes via parentViewController!.view.backgroundColor.... I get acces of the color of the parent view for example, that works. But how can I get acces of the outlets of the parentview? – Tom el Safadi Nov 04 '15 at 02:23
  • You probably have to cast it as it's view controller subclass. (self.parentViewController as! WhateverYourUIViewControllerSubclassIs).someProperty – Fred Faust Nov 04 '15 at 02:24
  • 1
    Thank you so, so, so much that worked for me!!! :))) – Tom el Safadi Nov 04 '15 at 02:27

1 Answers1

2

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

nPn
  • 16,254
  • 9
  • 35
  • 58
  • Thank you very much for your detailed answer. But I don't quite understand where I can get access of the label? The label is placed in the viewcontroller, like in the picture above. Sorry if I don't get it:D – Tom el Safadi Nov 05 '15 at 00:26
  • Did you figure it out? basically you get access to the label via the myContainerViewDelegate variable in your Container view. It could be as simple as myContainerViewDelegate.labelVariable.text. From that stand point it is not that different than just getting the parent view controller like you did before. The difference is that the Parent sets itself as the delegate and the child has no knowledge of the parent other than the protocol that is should implement (if you go the protocol route) – nPn Nov 05 '15 at 02:19