Notice
This site has been moved to http://www.kodesnippets.com
You can find this tutorial here: Container View in iOS
Updated for iOS 9.1
Hello everyone!
I hope everyone would be doing great.
I googled for a long time but I couldn’t find any good tutorial for Container View, I read a tutorial where two Container Views were stacked over one another to achieve the required task, which is certainly not the proper way to do it.
Anyway, I am going to do a tutorial on Container View. So, Lets get started without wasting any further time.
Create a new project and drag a Container View along with two Buttons over a View Controller.
Drag a View Controller and connect Container View Controller with an Empty Segue to it. After that select the newly added View Controller open the Size Inspector and set the Simulated Size to Freeform and adjust the width and height of the controller according to the Container View Controller.
Repeat the same step for a second View Controller.
Your Storyboard will more or less look like this:
After that, add three classes of type UIViewController, i.e two for child view controllers(Let’s say FirstViewController.swift and SecondViewController.swift) and one for container view controller(ContainerViewController.swift), also add a class of type UIStoryboardSegue. Add all these classes to View Controllers and Empty Segues on storyboard, respectively.
When done adding classes, give identifiers to Embedded and Empty segues.
Open up your ViewController.swift class, create two action functions of the buttons that you added in the start, and paste the following code inside:
class ViewController: UIViewController { var containerView: ContainerViewController? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func second(sender: AnyObject) { containerView!.segueIdentifierReceivedFromParent("buttonTwo") } @IBAction func first(sender: AnyObject) { containerView!.segueIdentifierReceivedFromParent("buttonOne") } override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "container"{ containerView = segue.destinationViewController as? ContainerViewController } } }
In your ContainerViewController.swift, paste the following code:
class ContainerViewController: UIViewController { var vc : UIViewController! var segueIdentifier : String! var lastViewController: UIViewController! override func viewDidLoad() { super.viewDidLoad() segueIdentifierReceivedFromParent("buttonOne") } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func segueIdentifierReceivedFromParent(button: String){ if button == "buttonOne" { self.segueIdentifier = "first" self.performSegueWithIdentifier(self.segueIdentifier, sender: nil) } else if button == "buttonTwo" { self.segueIdentifier = "second" self.performSegueWithIdentifier(self.segueIdentifier, sender: nil) } } override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == segueIdentifier{ //Avoids creation of a stack of view controllers if lastViewController != nil{ lastViewController.view.removeFromSuperview() } //Adds View Controller to Container "first" or "second" vc = segue.destinationViewController as! UIViewController self.addChildViewController(vc) vc.view.frame = CGRect(x: 0,y: 0, width: self.view.frame.width,height: self.view.frame.height) self.view.addSubview(vc.view) vc.didMoveToParentViewController(self) lastViewController = vc } } }
And in your Empty Segue class:
class Empty: UIStoryboardSegue{ override func perform() { } }
After that you’re good to go.
This project was built using Xcode 6.3.1 with SDK 8.3.
Here is a video of this project being run on a simulator.
I have uploaded this project on Github for reference.
Cheers!
Just wondering, is this is the right way to do it ?
LikeLiked by 1 person
I don’t know if its the right way because only an official Apple developer can tell that. but what I can tell you is that its the only proper way you would find on internet. 🙂
LikeLike
Thank you for this great job ! : )
I’m new to Apple-develop and do you have a objective-c sample there?
LikeLike
Hello anon!
I don’t have the sample for obj-c but I think I can try and write it for you.
LikeLike
There you go. Here is the link for Objective-C sample code: https://github.com/iaaqib/Container-View-Controller-
Cheers! 🙂
LikeLike
Hi Aaqib Hussain:
Thank you help me out of the problem, so kind of you ! [handshake] : )
LikeLike
Happy to help. 🙂
LikeLike
Hi, very nice tutorial. It’s working fine but I have added some textfield and buttons in first viewcontroller and second viewcontroller. How can i create action for these buttons? i am not able create action for these button. Please help me buddy.
LikeLike
Hello Ramachandran, I tried and I wasn’t able to create an action in the first attempt too. I know it sounds weird but in your first view controller create write a function lets say @IBAction func testButton(sender: UIButton){}. After that link your button to this function. it will create a connection. After that try control dragging your button in the class again it will work. It worked for me. 🙂
If you still have a question you can contact me at: aaqibhussain@kodesnippets.com
Peace!
LikeLike
Hi, Aaqib Hussain
you save my time, thanks for the great job
LikeLike
Hi, many thanks for that and for the Objctive-C version. Loved it. I hope you don’t mind my question but Would this approach be suitable if i want to visualise both the First and Second View at the same time, but stacked on top of each other in the screen? May be with a Stacked layout?
Many Thanks,
GC
LikeLike
I don’t think it will be useful for stacking views on top of each other. By Stack Layouts you mean StackView?
LikeLike
Can you help me?
How I can create IBOutlets using this approach? I tried but didn’t works.
LikeLike
@IBOutlets of the main buttons? The one I placed on the main screen?
LikeLike
At first or second view controllers.
LikeLike
Can you show me what you actually tried to do? your code?
LikeLike
Sure, what is your github user>
LikeLike
@iaaqib
LikeLike
I added you, take a look at iShopSDK.storyboard and its relative controllers WebOverlayController and RecommendationOverlayController at feature/overlay-in-app branch.
LikeLike
Checking
LikeLike
I downloaded the project I found is no WebOverlay or RecommendationOverlay Controller.
LikeLike
Sorry. found it.
LikeLike
Aaqib Hussain I discover my mistake in my own implementation of ContainerController I first set up my view controller and later move it to didMoveToParentViewController, but the correct way is first didMoveToParentViewController and later fill my view controller.
LikeLike
Sorry my internet is really slow today. It took ages to download the project. I’m glad to hear that. Kindly close the issue at github. Thanks.
LikeLike
If I want to access value of container child class from parent then what need to do?
LikeLike
I have a question, is there a way to not instantiate a new view controller every time i change views? For example lets say i change from First View Controller to the second view controller, can i retrieve the first view instead of creating a new instance of it? For example if i download a json in the first view, it will download again if i change views, there is a way to avoid that?
Great tutorial by the way.
LikeLike
I have followed 6 other posts and tutorials and tried 5 other Git Hub projects, all to fail. THIS ONE IS PERFECT. You perfectly execute passing data between container views. This has saved me from banging my head against the desk. Thank you !
LikeLike
Great tutorial. It helps me a lot. I am new to iOS development. I am having one issue that I have posted on https://stackoverflow.com/questions/46988502/fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-value-in-contai. Please help if possible.
LikeLike
You solved this problem ?
LikeLike
I have the same problem
https://stackoverflow.com/questions/46988502/fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-value-in-contai
What to do?
LikeLike