How to add an UIViewController's view as subview

IphoneUiviewUiviewcontroller

Iphone Problem Overview


Note to googlers, this Q-A is now six years out of date!

As Micky below and others mention, this is now done on an everyday basis with Containers in iOS.


I have a ViewController which controls many subviews. When I click one of the buttons I initialize another viewcontroller and show it's view as the subview of this view. However the subview exceeds the bounds of the frame for subview and infact fills the entire screen.

What could be wrong? I presume the problem is that UIViewController's view has a frame (0,0,320,460) and hence fills the entire screen (though it receive's touch events only when touched within the subview frame bounds). How can I resize the frame to fit as subview.

In short, I need help adding a viewcontroller's view as a subview to another viewcontroller's view.

Thanks!

Iphone Solutions


Solution 1 - Iphone

As of iOS 5, Apple now allows you to make custom containers for the purpose of adding a UIViewController to another UIViewController particularly via methods such as addChildViewController so it is indeed possible to nest UIViewControllers

EDIT: Including in-place summary so as to avoid link breakage

I quote:

> iOS provides many standard containers to help you organize your apps. However, sometimes you need to create a custom workflow that doesn’t match that provided by any of the system containers. Perhaps in your vision, your app needs a specific organization of child view controllers with specialized navigation gestures or animation transitions between them. To do that, you implement a custom container - Tell me more...

...and:

> When you design a container, you create explicit parent-child relationships between your container, the parent, and other view controllers, its children - Tell me more

Sample (courtesy of Apple docs) Adding another view controller’s view to the container’s view hierarchy

- (void) displayContentController: (UIViewController*) content
{
   [self addChildViewController:content];                 
   content.view.frame = [self frameForContentController]; 
   [self.view addSubview:self.currentClientView];
   [content didMoveToParentViewController:self];          
}

Solution 2 - Iphone

Thanks to this guys I did it http://highoncoding.com/Articles/848_Creating_iPad_Dashboard_Using_UIViewController_Containment.aspx

Add UIView, connect it to header:

@property (weak, nonatomic) IBOutlet UIView *addViewToAddPlot;

In - (void)viewDidLoad do this:

ViewControllerToAdd *nonSystemsController = [[ViewControllerToAdd alloc] initWithNibName:@"ViewControllerToAdd" bundle:nil];
    nonSystemsController.view.frame = self.addViewToAddPlot.bounds;
    [self.addViewToAddPlot addSubview:nonSystemsController.view];
    [self addChildViewController:nonSystemsController];
    [nonSystemsController didMoveToParentViewController:self];

Enjoy

Solution 3 - Iphone

This answer is correct for old versions of iOS, but is now obsolete. You should use Micky Duncan's answer, which covers custom containers.

Don't do this! The intent of the UIViewController is to drive the entire screen. It just isn't appropriate for this, and it doesn't really add anything you need.

All you need is an object that owns your custom view. Just use a subclass of UIView itself, so it can be added to your window hierarchy and the memory management is fully automatic.

Point the subview NIB's owner a custom subclass of UIView. Add a contentView outlet to this custom subclass, and point it at the view within the nib. In the custom subclass do something like this:

- (id)initWithFrame: (CGRect)inFrame;
{
	if ( (self = [super initWithFrame: inFrame]) ) {
		[[NSBundle mainBundle] loadNibNamed: @"NibNameHere"
		                              owner: self
		                            options: nil];
		contentView.size = inFrame.size;
		// do extra loading here
		[self addSubview: contentView];
	}
	return self;
}

- (void)dealloc;
{
	self.contentView = nil;
	// additional release here
	[super dealloc];
}

(I'm assuming here you're using initWithFrame: to construct the subview.)

Solution 4 - Iphone

I feel like all of these answers are slightly incomplete, so here's the proper way to add a viewController's view as a subview of another viewController's view:

    [self addChildViewController:viewControllerToAdd];
    [self.view addSubview:viewControllerToAdd.view];
    [viewControllerToAdd didMoveToParentViewController:self];

If you'd like, you can copy this into your code as a snippet. SO doesn't seem to understand code replacement formatting, but they will show up clean in Xcode:

    [self addChildViewController:<#viewControllerToAdd#>];
    [self.view addSubview:<#viewControllerToAdd#>.view];
    [<#viewControllerToAdd#> didMoveToParentViewController:self];

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/occ/instm/UIViewController/willMoveToParentViewController">willMove</a> is called automatically w/ addChild. Thanks @iOSSergey

> When your custom container calls the addChildViewController: method, it automatically calls the willMoveToParentViewController: method of the view controller to be added as a child before adding it.

Solution 5 - Iphone

Use:

[self.view addSubview:obj.view];

Solution 6 - Iphone

Change the frame size of viewcontroller.view.frame, and then add to subview. [viewcontrollerparent.view addSubview:viewcontroller.view]

Solution 7 - Iphone

You must set the bounds properties to fit that frame. frame its superview properties, and bounds limit the frame in the view itself coordinate system.

Solution 8 - Iphone

You may use PopupController for the same one the SDK which shows UIViewController as subview You may check PopupController

Here is sample code for the same

popup = PopupController
        .create(self.navigationController!)
        .customize(
            [
                .layout(.center),
                .animation(.fadeIn),
                .backgroundStyle(.blackFilter(alpha: 0.8)),
                .dismissWhenTaps(true),
                .scrollable(true)
            ]
        )
        .didShowHandler { popup in
        }
        .didCloseHandler { popup in
    }
    let container = MTMPlayerAndCardSelectionVC.instance()
    container.closeHandler = {() in
        self.popup.dismiss()
    }
    
    popup.show(container)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsperumalView Question on Stackoverflow
Solution 1 - IphoneMickyDView Answer on Stackoverflow
Solution 2 - IphoneNaloiko EugeneView Answer on Stackoverflow
Solution 3 - IphoneSteven FisherView Answer on Stackoverflow
Solution 4 - IphoneLoganView Answer on Stackoverflow
Solution 5 - Iphonerahul guptaView Answer on Stackoverflow
Solution 6 - IphoneCiNNView Answer on Stackoverflow
Solution 7 - IphonebolekView Answer on Stackoverflow
Solution 8 - IphoneAnjali jariwalaView Answer on Stackoverflow