I have 2 ViewControllers.
VC1 has a 2 views inside it.
I want to get MenuUIVC to appear in one of my views belonging(child) to VC1.
I tried this code inside of VC1 but it didn't work.
MenuUIVC * menuViewVC = [[MenuUIVC alloc] init];
menuUIView = menuViewVC.view;
I expected to be able to see the MenuUIVC inside the view (menuUIView) which is a child of VC1. I have the IBOutlets all hooked up on the storyboard.
You can use Container views to get View Controller inside a View Controller. And, you can get the reference to it through prepareForSegue() method.
Links for description:
iOS Container View
The Easy Way to Switch Container Views in iOS
If you are using UIView, then why don't you use
[menuUIView addSubview:menuViewVC.view];
Another option is to use childviewcontrollers.
See these links for example:-
adding view controller as child view in ios
Add child view controller to current view controller
Using container or child view controller, gives you full fledge option of using View Controller properties, which you will not get in UIView.
Say for example, you can you orientation delegate methods, which you can't using in UIView class directly.
Hope this can help you.
Cheers
Sanjay
you can go for container view if you want to do it using IBOutlets & storyborad.
but if you want to do it using code then follow the below steps :
initialise & create parent view controller.
then add required child view as a subview with negative frame.
now change the frame with UIView animation whenever required. & do add tap gesture recogniser on part of screen other than the child view to remove it back to the initial position.
Both the methods add the view as child of parentview and view can receive events. When to use which one?
It all depends on how you want to manage the new subview. If you want the new subview to be managed by the current view's view controller (e.g. you're adding something simple like a few UILabel objects), you simply call addSubview. If, on the other hand, the new subview has its own view controller (i.e. it's sufficiently complicated collection of views, with rich functionality, that you want to encapsulate all of this complexity with its own controller to manage everything this new subview does) then you call addChildViewController to add the new view controller, but then call addSubview, too.
So, note that addChildViewController, itself, does nothing with the views. You generally immediately follow it with calls that add its view, too, e.g. here is a slightly clarified example from the Implementing a Custom Container View Controller section of the View Controller Programming Guide for iOS:
[self addChildViewController:childViewController]; // add subview's view controller
childViewController.view.frame = ... // specify where you want the new subview
[self.view addSubview:childViewController.view]; // now you can add the child view controller's view
[childViewController didMoveToParentViewController:self]; // now tell the child view controller that the adding of it and its views is all done
So, it's not a question of addSubview vs addChildViewController, but rather addSubview vs addChildViewController+addSubview. If you call addChildViewController, you're doing so with the intent of calling addSubview for its view at some point.
Frankly, this question of addSubview vs. addChildViewController+addSubview is rarely how we think about this. A more logical way of thinking of this is determine whether this new view has its own view controller. If it does, you perform the addChildViewController sequence of calls. If not, you just call addSubview.
For a good introduction to view controller containment (e.g. the rationale for that API, the importance of keeping the view hierarchy synchronized with the view controller hierarchy, etc.), see WWDC 2011 video Implementing UIViewController Containment.
They are very different. addChildViewController associates a view controller with a parent container view controller, while addSubview adds a view to the view hierarchy of the view it is being added to. In the former case, the new child view controller will be responsible for handling events when it is the selected view controller of its parent. Think of a tab bar controller--each tab has its own associated "child" view controller that displays its view within the parent tab bar controller's content area and handles any user interaction within that view when its corresponding tab is selected in the tab bar. You should only use addChildViewController when you have a custom container view and want to add a new view controller to its childViewControllers property. If you just want to add a new view to the view hierarchy that can receive events, which is what it kind of sounds like, addSubview is the way to go. "Implementing a Container View Controller" section explains what addChildViewController is for.
addChildViewController is method in UIViewController class and
addSubview is in UIView class
Both have entirely different behavior.
addChildViewController just puts a view controller in front of the current one. You have to manage the flow of controllers. This method is only intended to be called by an implementation of a custom container view controller.
addSubview adds another view as sub view to the view of that object.
Knowing that MVC means Model-View-Controller:
If you only intend to add the view, then use addSubview. e.g. adding a label, button.
However if you intend to a d view + controller then you must use addChildViewController to add its controller and ALSO addSubView to add its view. e.g. adding another viewController, tableViewController.
In addition:
There are two categories of events that are forwarded to child view controllers:
1- Appearance Methods:
- viewWillAppear:
- viewDidAppear:
- viewWillDisappear:
- viewDidDisappear:
2- Rotation Methods:
- willRotateToInterfaceOrientation:duration:
- willAnimateRotationToInterfaceOrientation:duration:
- didRotateFromInterfaceOrientation:
An example of where you would run into an issue if you don't do such is here
For more information I strongly recommend to see answers on this question.
Available from iOS 5, the addChildViewController:
- (void)addChildViewController:(UIViewController *)childController NS_AVAILABLE_IOS(5_0);
method let you add any view controller as a child to some other view controller, but first it removes any parent from the childController and than add it as a child view controller to the specified controller.
The child controller is nothing but an instance of UIViewController and thus it will provide the functionality of view controller (i.e it will receive the events like -(void)viewWillAppear, -(void)viewWillDisappear, etc as a normal UIViewController does).
On the other hand
- (void)addSubview:(UIView *)view;
addSubview: will add any view as subview on any other view.
It's not the choice which to use when rather it's the type which asks to use specific method.
For Instance -
If you have an instance of UIViewController than you will definitely use addChildViewController: (also you can use presentModalViewController, pushViewController) and if you have an instance of UIView than definitely you have to use addSubview.
Note : You can also add view controller's view as a subview to any other view as well.
Based on some test, I found that: If child view controller is not added to parent view controller (supposing the parent view controller is under the root view controller), only child view controller's view is added to parent view controller's view, then:
the sub view controller can still receive messages directly related to view, such as - viewWillAppear:, - viewWillLayoutSubviews, etc.
But
the sub view can not receive some system messages, such as - willRotateToInterfaceOrientation:duration:
I can't give the messages list now, however.
addChildViewController is used to prevent the added sub view controller from releasing, in other word, the parent view controller will hold a strong reference to the sub view controller.
I have multiple view controllers which should load a specific view like in this drawing. I defined that view in the storyboard as a separate view controller. The reusable view controller has some methods which make the view work. What's the best way to do this?
I tried using addSubview method but the IBOutlets won't initialize. Please help me.
You probably want to use a container view.
With a container view, you can embed different view controllers in the same view. Hooking them up is really easy, and can be done within the storyboard.
This might be a stupid question, but I'll shoot.
I made a little test project to test out a concept I had for a sliding view controller type of thing. I naively assumed I could create a UIView (let's call it peekView) with an outlet in a controller, and call something like [slidingControllerSlideFrom:self.view] from any visible view controller, the implementation of such being:
- (void)slidingControllerSlideFrom(UIView*)controllersMainView
{
// push side controller to top of navigation stack
self.peekView = controllersMainView;
// sliding animation
}
But there is no effect. No crash, no warning, no change of view in the pushed controller.
Of course, the pushed controller crashes when trying to add self's view as a subview, but assigning it to a predefined UIView just results in nothing.
So, why? And if a mere 'why' is not enough of a question- what happens when I try to assign one controller's view another controller's subview, and what was the reason for designing UIKit where you cannot set views from self.view?
To do that you have two options:
1 - If the controller in the peekView is always the same one in a given scene, use a "Container View". Those are explained here. Basically, they allow you to add a view in your scene that is managed by another controller.
2 - If the controller in the peekView depends on different conditions, you will have to create something similar to a custom tabbarcontroller. That means that you instantiate the controller that you need, add it's view as a subview of peekView (not assign the controller's view to the peekView itself) and then use didmovetoparentviewcontroller to notify the child controller. This question might help.
UPDATE:
Just saw your comment, so let me answer what you actually asked: The peekview property is actually just a reference to the real UIView you placed in the screen. When you do this:
self.peekView = controllersMainView;
You are changing the reference, but no the view object itself. That's why you are not seeing any changes. There are ways of adding a new view to the controller from code, but it is much simpler to simply use addSubview to add your controllers view to a UIView that is already in the controller.
Check out the discussion here: subView Slide up from bottom of the screen
and here: SubView slide in animation, iphone
Hopefully that gives you a bit of framework on how to approach this task!
I have encapsulated all my table view logic on a UITableViewController that is linked to a view. This was done using storyboards.
I would like to embed this logic and view within another view controller / view (kind of like a header information with a scrollable table beneath.)
I have the following components:
CustomViewController which is linked to a UIView (dragged in from storyboard)
CustomTableViewController which is linked to a UITableView (dragged in from storyboard)
Essentially I am trying to mimic the scenario of the Stopwatch in the iOS clock app
What is the beast approach to this?
How is it done programatically?
Can this be done on the storyboard somehow?
Any help would be greatly appreciated. Thanks
Ok figured it out. This solution is iOS 5 specific since this feature was added there. This method works with storyboards.
Setup: The intention is to host one view controllers view and logic within another controller.
Since there is no intrinsic way to reference the child view controller in the storyboard, we need to give the view controller a name. This can be done by filling out the "Identifier" attribute on the controller in the storyboard. NOTE: Make sure you are giving the controller the identifier and not the controllers view.
Instantiate the controller you want to aggregate. This can be done from the hosting controller.
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"ControllerIdentifier"];
Add the child controller to the parent controller
[self addChildViewController: controller];
Add the child controllers view to the parent controllers view. Note if you have a place holder view in the parent controller you wish to add the child view to, then this is where you do it. Here I add it the a UIView called stage in the parent controller.
[self clearStage];
[self.stageView addSubview:controller.view];
presentedController.view.frame = self.stageView.bounds;
And that is it. Pretty simple. I have used it successfully with switching controllers and view in a home made tab control. The sub controller enlists its views in the view lifecycle, so the viewDidLoad, etc all work as expected in this child view controller.
Hopes this helps someone.