I'm coming from as AS3 background so it might be easier for me to show you what I'm trying to do with AS3. I have a UIViewController(root) and inside that I have a ContainerView. I am under the impression that the container view's UIViewController is a child of the UIViewController(root). I would like a button to be pressed on the child view controller (container view) and bubble that event up to the parent(root UIViewController). In AS3 I would have something like this
Root Class creates the child class
var childClass = new ChildClass()
childClass.addEventListener("buttonWasPressed", callThisFunction);
private function callThisFunciton(e:Event):void
{
// move the child view
TweenLite.to(childClass,1,{x:100});
}
And in the Child Class I have a button function that would deploy this event that would bubble up to the parent.
dispatchEvent(new Event("buttonWasPressed", true));
What I'm not sure how to do is get the root VC listening for that event. Because I'm using a containerView I'm not sure how to set up an outlet to that child VC and listen to things that the child is doing. I can control drag from the IB to the VC, but that just created an outlet for a UIView that represents the container view. When I println some text, I can see that the child view controller is being instantiated first before the parent VC.
I found this post that I think is pointing in the right direction. https://craiggrummitt.wordpress.com/2014/07/14/communication-between-objects-in-objective-c-and-swift-compared-with-actionscript-part-5/
But I'm getting an error, most likely because I'm not sure how to make the connection from parent VC to child VC that's inside the container view. I have looked around and I can't seem to find much information on the topic.
Thanks for the help!
There are two ways:
1) Use a delegate protocol (recommended)
a) In your child, create a delegate protocol, and an optional property on the child VC that will hold the delegate.
b) In the delegate protocol create a method that will be called when the button was pressed, and implement a
buttonWasPressed()
method in the child that calls this method on the delegate. (You'll want to connect this method up with a button in the storyboard)c) Make your parent view controller conform to the child protocol
c) When the child is embedded in the parent a special kind of segue is run called an embed segue. You can see it in the storyboard - it’s the line that connects the child to the parent:
Add an identifier to that segue in the storyboard:
And a constant for it in the parent view controller:
d) Then in the parent view controller, override the
prepareForSegue()
method and check ifsegue.identifier
matches what you had set as the identifier. If it does, then you can get a reference to the child view controller throughsegue.destinationViewController
. Cast this as your child view controller, then you can set the parent to be its delegate:e) Win!
2) Use NSNotification and NSNotificationCenter
You can think of these as similar to ActionScript events, however they don’t automatically bubble up through the view hierarchy like AS. Instead notifications are dispatched globally through
NSNotificationCenter
. I prefer to only use this when there are multiple objects that need to listen for one particular event.You can find more information about
NSNotification
andNSNotificationCenter
here: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Well or you can use static variables, which is probably the most straightforward way.