I don't know if this is the right key to search "add UIViewController in subview".
As what you can see in my image ,there are two ViewController, the main and the second controller. Inside the main controller there is a UIView(blue background color). Inside in UIView, I want to add the second ViewController in my UIView. I have this code but It didn't work.
here's my code
#import "ViewController.h"
#import "SampleViewController.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UIView *testView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
SampleViewController * sample = [[SampleViewController alloc] initWithNibName:#"SampleViewController" bundle:nil];
sample.view.frame = CGRectMake(0, 0, self.testView.bounds.size.width, self.testView.bounds.size.height);
[self.testView addSubview:sample.view];
}
#end
I want to know if this is possible? I know initWithNibName: works in xib file, I don't the exact term to search in google about this. I'm just trying to experiment something if this is possible in IOS. Hoping you understand what I'm trying to do. Hoping for your advice. Thanks in advance
here's my update
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UIView *testView;
#property(strong,nonatomic) SampleViewController * samples;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIStoryboard *storyBoard = self.storyboard;
SampleViewController * sample = [storyBoard instantiateViewControllerWithIdentifier:#"SampleViewController"];
// SampleViewController * sample = [[SampleViewController alloc] //initWithNibName:#"SampleViewController" bundle:nil];
[self displayContentController:sample];
//commented the below line because it is not needed here, use it when you want to remove
//child view from parent.
//[self hideContentController:sample];
}
- (void) displayContentController: (UIViewController*) content;
{
[self addChildViewController:content]; // 1
content.view.bounds = self.testView.bounds; //2
[self.testView addSubview:content.view];
[content didMoveToParentViewController:self]; // 3
}
- (void) hideContentController: (UIViewController*) content
{
[content willMoveToParentViewController:nil]; // 1
[content.view removeFromSuperview]; // 2
[content removeFromParentViewController]; // 3
}
I always get this error
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/ace/Library/Developer/CoreSimulator/Devices/035D6DD6-B6A5-4213-9FCA-ECE06ED837EC/data/Containers/Bundle/Application/EB07DD14-A6FF-4CF5-A369-45D6DBD7C0ED/Addsubviewcontroller.app> (loaded)' with name 'SampleViewController''
I think, its looking for a nib. I didn't implement a nib here.
You should use Child containment concept, here MainViewController is a parent view controller and you want to add child view controller view as a subview on Main View Controller.
Adding and Removing a Child
//call displayContentController to add SampleViewCOntroller view to mainViewcontroller
[self displayContentController:sampleVCObject];
// write this method in MainViewController
- (void) displayContentController: (UIViewController*) content;
{
[self addChildViewController:content]; // 1
content.view.bounds = testView.bounds; //2
[testView addSubview:content.view];
[content didMoveToParentViewController:self]; // 3
}
Here’s what the code does:
It calls the container’s addChildViewController: method to add the child. Calling the addChildViewController: method also calls the child’s willMoveToParentViewController: method automatically.
It accesses the child’s view property to retrieve the view and adds it to its own view hierarchy. The container sets the child’s size and position before adding the view; containers always choose where the child’s content appears. Although this example does this by explicitly setting the frame, you could also use layout constraints to determine the view’s position.
It explicitly calls the child’s didMoveToParentViewController: method to signal that the operation is complete.
//you can also write this method in MainViewController to remove the child VC you added before.
- (void) hideContentController: (UIViewController*) content
{
[content willMoveToParentViewController:nil]; // 1
[content.view removeFromSuperview]; // 2
[content removeFromParentViewController]; // 3
}
For more details, please refer to apple doc:
https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html
Configuring a Container in Interface Builder, for those who don't want to write code.
To create a parent-child container relationship at design time, add a container view object to your storyboard scene, as shown in Figure 5-3. A container view object is a placeholder object that represents the contents of a child view controller. Use that view to size and position the child’s root view in relation to the other views in the container.
When you load a view controller with one or more container views, Interface Builder also loads the child view controllers associated with those views. The children must be instantiated at the same time as the parent so that the appropriate parent-child relationships can be created.
You can do this simply by using StoryBoards
Open storyboards and select the view controller in which your Blue view is present, open Utilities search for ContainerView and drag it into your blue view, this will automatically adds an view controller that acts as child view for your view. You can resize your container view in size inspector.
I've resolved the problem about the uiview on second uiviewcontroller.
Follow the code that I've used:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SecondViewController *sb = (SecondViewController *)[storyboard instantiateViewControllerWithIdentifier:#"sb"];
sb.view.backgroundColor = [UIColor redColor];
[sb willMoveToParentViewController:self];
[self.view addSubview:sb.view];
[self addChildViewController:sb];
[sb didMoveToParentViewController:self];
I hope to help you.
Thanks a lot
SampleViewController * sample = [[SampleViewController alloc] initWithNibName:#"SampleViewController" bundle:nil];
sample.view.frame = CGRectMake(0, 0, self.testView.bounds.size.width, self.testView.bounds.size.height);
[self addChildViewController:sample];
[self.testView addSubview:sample.view];
You can add a childViewController to UIViewController since iOS5..
it is a great way to maker smaller, more reusable viewControllers, I also really like it.
you're really close, but you just need a couple more lines of code..
///
[self addChildViewController:sample];
[self.testView addSubview:sample.view]; //you already have this..
[sample didMoveToParentViewController:self];
In you viewWillDisappear: or one of the other teardown methods you'll need to clean up like this:
//we'll need another pointer to sample, make it an iVar / property..
[sample willMoveToParentViewController:nil]; // 1
[sample removeFromSuperview]; // 2
[sample removeFromParentViewController]; // 3
You can read the Apple docs on containing child viewControllers here https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html
I'm tring to adding UIViewController in subview, and this work.
On UIViewController I've added 2 button, in .h file:
-(IBAction)matchButtonAction:(id)sender;
-(IBAction)closeButtonAction:(id)sender;
And in .m file:
-(IBAction)matchButtonAction:(id)sender
{
NSLog(#"matchButtonAction");
}
-(IBAction)closeButtonAction:(id)sender
{
NSLog(#"closeButtonAction");
}
but I don't see the log.
I need to add same parameter on UIViewController instantiateViewControllerWithIdentifier?
How to resolve the problem?
My UIViewController initialization is:
AlertDialogViewController *alertDialogView = (AlertDialogViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"alertDialogView"];
[alertDialogView willMoveToParentViewController:self];
[viewController.view addSubview:alertDialogView.view];
[viewController addChildViewController:alertDialogView];
[alertDialogView didMoveToParentViewController:viewController];
Since your view controller is in storyboard you should use instantiateViewControllerWithIdentifier to get the VC from storyboard.
SampleViewController * sample = [self.storyboard instantiateViewControllerWithIdentifier:#"IdOfSampleViewController"];
sample.view.frame = CGRectMake(0, 0, self.testView.bounds.size.width, self.testView.bounds.size.height);
[self.testView addSubview:sample.view];
Don't forget the add the identifier for the SampleViewController in storyboard
I've try to use this code:
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:nil bundle:nil];
secondViewController.view.frame = CGRectMake(0, 0, self.mySubView.bounds.size.width, self.mySubView.bounds.size.height);
[self addChildViewController:secondViewController];
[self.viewDialogSolution addSubview:secondViewController.view];
but I see only myview not the layout of secondViewController.
Ho to resolve the probleam?
Thanks a lot
let controller:SecondViewController =
self.storyboard!.instantiateViewController(withIdentifier: "secondViewController") as!
SecondViewController
controller.view.frame = self.view.bounds
controller.willMove(toParent: self)
self.view.addSubview(controller.view)
self.addChild(controller)
controller.didMove(toParent: self)
Related
What I did:
I am using scrollview to view some UIView(s), with paging enabled.
In last page in subview of scrollView I added a button.
I also wrote a function which is in subclass of UIView ,which is invoked when we press that button.
I want to view storyboard when I press that button.
You need to implement protocol method for custom UIView class.
For example;
#import <UIKit/UIKit.h>
#protocol YourCustomViewDelegate <NSObject>
- (void)buttonTapped;
#end
#interface YourCustomView : UIView
#property (nonatomic, strong) id< YourCustomViewDelegate > delegate;
#end
And the .m file you can call buttonTapped delegate method.
- (void)myCustomClassButtonTapped:(id)sender
{
[self.delegate buttonTapped];
}
For proper work;
set your custom view delegate to self in your custom view controller.
add buttonTapped method to that view controller
And do what you want in that method. Present/Push view controllers like the other answers explained.
Edit
I will try to illustrate very simple usage of protocols, hope it will help you.
#import "MyViewController.h"
#import "YourCustomView.h"
#interface MyViewController ()<YourCustomViewDelegate> // this part is important
#end
#implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
YourCustomView *customView = // initialize your custom view, I suppose that you already did it
customView.delegate = self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)buttonTapped
{
YOUR_VIEW_CONTROLLER_CLASS *viewCon =[storyboard instantiateViewControllerWithIdentifier:#"mainVC"]; //mainVC is just a example and u will have to replace it with your viewController storyboard id
//Pushing VC
[self.navigationController pushViewController:viewCon animated:YES];
}
Take a look at this
YourViewController *obj=[[YourViewController alloc]init];
UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:obj];
[[[UIApplication sharedApplication]keyWindow].rootViewController presentViewController:nav animated:YES completion:NULL];
try like this
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController* initialView = [storyboard instantiateInitialViewController];
Firstly you need to set a storyboard Id to your ViewController, namely "mainVC". Then you could pus/present it using below code :-
YOUR_VIEW_CONTROLLER_CLASS *viewCon =[storyboard instantiateViewControllerWithIdentifier:#"mainVC"]; //mainVC is just a example and u will have to replace it with your viewController storyboard id
//Pushing VC
[self.navigationController pushViewController:viewCon animated:YES];
//OR presenting VC
[self presentViewController:viewCon animated:YES completion:nil];
Also in case if you want your another storyboard to be initiated then below,
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil]; //Change MainStoryboard with your storyboard id
hope this will help
the way i perceive your question is
->Rightnow your inside you are in UIView class and inside it there is a button by clicking it you want to push or present a ViewController and offcourse from inside your UIView class you cant push or present your view Controller. So
you can do one simple thing first inside action method make a ref(forward declaration) or you can make a whole new object of your ViewController class in which your UIView is present right now , then call a function(which exist in your ViewController) like
//function inside your uiview calss
- (void)btnaction
{
[_objCSInformationViewController pushViewController];
}
// function inside your view controller
-(void)pushViewController
{
yourViewController *objViewController = [[yourViewController alloc]initWithNibName:#"yourViewController" bundle:nil];
[strong.navigationController pushViewController:objViewController animated:YES];
}
I have a problem in my app.
When I pass a UIView to a SecondViewController in this way
SecondViewController *second = [self.storyboard instantiateViewControllerWithIdentifier:#"secondviewcontroller"];
second.currentView = currentView;
(second.currentView is my property in SecondViewController and I pass to it my view)
At this point, it's all ok and my SecondViewController show correctly my currentView, but when I retund in FirstViewController my currentView disappear!!!
Why? Can you help me? thanks
UPDATE
in FirstViewController.h
IBOutlet UIView *currentView;
in FirstViewController.m
SecondViewController *second = [self.storyboard instantiateViewControllerWithIdentifier:#"secondviewcontroller"];
second.currentView = currentView;
[self presentViewController:second animated:NO completion:nil];
in SecondViewController.h
#property (nonatomic, strong) UIView *currentView;
in SecondViewController.m
- (void) viewDidAppear:(BOOL)animated{
[self.view addSubview:self.currentView];
self.currentView.center = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2);
}
this is my code in the two ViewControllers, and when I return in FirstViewController currentView there isn't... it disappear...
A view only have super view, so when you add the view to SecondViewController you care adding it to its view hierarchy and thus removing to from your current view controller. When you call something like:
- (void) viewDidLoad{
[super viewDidLoad];
// Here the view is removed the first view and placed on the second view.
[self.view addSubView:self.secondView];
}
Thus if you want to add it back in the first view you need to add it again to view hierarchy of the first view.
A beter solution would be pass the data to the next view controller, not to view but the model. Like pass the model object holding the data presented in the view.
I solved my issue!!!
When I return in FirtsViewController I must add a new time my view in my self.view at last position, in this way:
[self.view addSubview:currentView];
[currentView setCenter:initially_center_view];
in this way I see my view!!!
I've created an app that uses a bunch load of Container views. Today i've found out that embedded segues are not supported in iOS 5 (thanks Xcode for letting me know.)
So right now I have a lot of embedded segues that passes data between one another.
I'm using this code to load ViewControllers inside a UIView instead of the Container from the IB:
RootViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
NewsViewController *news = [storyboard instantiateViewControllerWithIdentifier:#"NewsViewControllerID"];
news.view.frame = self.newsSection.bounds;
[self.newsSection addSubview:news.view];
[self addChildViewController:news];
[news didMoveToParentViewController:self];
// Do any additional setup after loading the view.
}
How can I use the above and still pass data to NewsViewController (something like prepare for segue)
I've tried inserting in the above something like
NewsViewController *news = [storyboard instantiateViewControllerWithIdentifier:#"NewsViewControllerID"];
news.view.frame = self.newsSection.bounds;
news.myLabel.text = #"Test";
[self.newsSection addSubview:news.view];
But the label won't change.
I prefer just to pass the data and not use a singleton or delegation.
Thanks
I would recommend creating a public method, from where you could pass the data you need on your NewsViewController controller. Still, the issue right now is that the you are updating the UI before it has been initialised. Also I would recommend you to have a look on how to create content UIViewControllers, because right now you are only adding its UIView. Check this document from Apple, look at the section Implementing a Custom Container View Controller. And this part of the code:
- (void) displayContentController: (UIViewController*) content;
{
[self addChildViewController:content]; // 1
content.view.frame = [self frameForContentController]; // 2
[self.view addSubview:self.currentClientView];
[content didMoveToParentViewController:self]; // 3
}
So in your case, after the step 3 has been made, you could pass the values you want to use inside your NewsViewController.
The problem could be that at the moment you are setting the text of the label, the label is still nil.
Try adding an NSString property to your NewsViewController (e.g. labelText), and in viewDidLoad do self.myLabel.text = self.labelText;.
you have pass the string your next view controller and viewDidLoad you have to the string.
Its not working because your view not yet created and if check the instance of UIlabel it will nil. So you have set the text in your next viewcontroller when it loaded in the memory.
Edit
you have create a property variable of NSString type(textString) in NewsViewController and pass the string as news.textString = #"Test";
and the in ViewDidLoad of NewsViewController set that string to label as myLabel.text = textString;
Better Explanation
-Declare NSString property in the NewsViewController.h
#property (strong, nonatomic) NSString *assignText;
-Instantiate normally, but assign the string and not the label.
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
NewsViewController *news = [storyboard instantiateViewControllerWithIdentifier:#"NewsViewControllerID"];
news.assignText = #"Test";
[self addChildViewController:news];
-Then in your NewsViewController viewDidload, assign the label to the string.
-(void)viewDidLoad {
[super viewDidLoad];
self.myLabel.text = self.assignText;
}
I'm using a UIStoryBoard to allow the FirstViewController to add the view of second ViewController as a subview. On removing the sub view using the following method
FirstViewController.m
- (IBAction) btnMoveTo:(id)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"Second"];
vc.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:vc animated:NO];
}
SecondViewController.m
-(void)viewDidLoad{
self.view.opaque = YES;
self.view.backgroundColor = [UIColor clearColor];
}
- (IBAction) withDraw:(id)sender{
[self.view removeWithZoomOutAnimation:2 option:nil];
}
When I access the withDraw Function, the view of the SecondViewController is removed and firstViewController is back. However when I use the button to access the - (IBAction) btnMoveTo:(id)sender function. It doesn't work. Nothing really happens. Any suggestions or help would be greatly appreciated.
You are confusing views with view controllers. View controllers are objects that control views, so for the first line you wrote,
I'm using a UIStoryBoard to allow the FirstViewController to add the view of second ViewController as a subview. On removing the sub view using the following method
you cant add a view controller as a subview of another view controller. You present a view controller that manages its own views, and you can add UIViews as subviews of a UIViewController. A UIViewController manages UIViews.
The problem you are having with the code you posted, is that when you trigger the withDraw: function, you are removing the view of the view controller. Not the view controller itself. You need to dismiss the SecondViewController to gain access of the FirstViewController again.
How can I create a UIPopoverController with integrated UINavigationController so I will be able to slide views inside the UIPopoverController left-right (with navigation bar).
UPDATE:
I open popup like this
- (void)showSettingsViewAtSenderForIPad:(id)sender
{
if (!settingsPopoverController_)
{
SettingsPopoverController *settings = [[SettingsPopoverController alloc] init];
settings.valuesGeneratorOptions = valuesGeneratorOptions_; // setting variables
self.settingsPopoverController_ = [[[UIPopoverController alloc] initWithContentViewController:settings] autorelease];
[settingsPopoverController_ setDelegate:self];
[settingsPopoverController_ setPopoverContentSize:CGSizeMake(320, 480)];
[settings release];
}
if (!infoPopoverController_.popoverVisible)
{
[settingsPopoverController_ presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
}
}
I created a controller which has a NSTableViewController as a root controller in UINavigationController
#interface SettingsPopoverController : UIViewController
{
ValuesGeneratorOptions *valuesGeneratorOptions;
IBOutlet SettingsViewController *settingsViewController;
IBOutlet UINavigationController *navigationController;
}
...
#implementation SettingsPopoverController
...
- (void)viewDidLoad
{
self.settingsViewController.valuesGeneratorOptions = self.valuesGeneratorOptions;
[self.view addSubview:self.navigationController.view];
[super viewDidLoad];
}
...
end
The problem is, that the table is not scrollable inside the popup. It also ignores the table style (initWithStyle not called).
Fix?
SOLUTION:
Found the solution: popOver table view
You create a new nib and a UIViewController. This nib has, as it's top level view, a plain jane UIView and a UINavigationController. The UINavigationController's top UIViewController is whatever view controller you want to display first.
You then display this nib inside your popover controller. In the view did load, you do something like this:
-(void)viewDidLoad
{
[self.view addSubview:self.navigationController.view];
}
This adds your navigation controller's view to your view in your nib, which allows it to be displayed.