I have a tabview controller to which I added a UIViewController to each tab. I want to have multiple UIViews inside the UIViewController.
So in the implementation of the UIViewController class I added [self.view addSubView:uiview1] and [self.view addSubView:uiview2]. The problem is that when I run the app, it crahes on load.
However, if I only used a single UIView and did: self.view = UIView1 that would work fine.
Does anyone know what is causing the problem? Or if I'm doing something fundamentally wrong?
Assuming you are doing this programmatically, you're supposed to create the view in the view controller's loadView method. So you must do this:
self.view = [[[UIView alloc] initWithFrame:someFrame] autorelease];
before you do this:
[self.view addSubview:uiview1];
[self.view addSubview:uiview2];
Otherwise, self.view would be nil.
There's no reason you can't have multiple views within your UIViewController's main view member variable. However, there are quite a few items left unanswered in your question:
How are you obtaining view1 and view2?
Are they outlets in your XIB file (are you using a XIB file, or creating everything in code), or are you creating them in code?
Where in your UIViewController subclass are you adding them to your view member variable?
What's the message printed to the console when it crashes?
Related
I want to add a UIViewController class to an existing class as a subview, so i used the following code.
myEventsView = [[EventNameViewController alloc]initWithNibName:#"EventNameViewController" bundle:nil];
[myEventsView.view setFrame:CGRectMake(0, 39, 320, 400)];
[self.view addSubview:myEventsView.view];
It is added successfully but the problem is with button actions, those actions which have to navigate to other view controllers are not working. Those action methods are called, but action not performed, not getting why so, please guide for the above.
Thanks in advance.
Try
myEventsView = [[EventNameViewController alloc]initWithNibName:#"EventNameViewController" bundle:nil];
[myEventsView.view setFrame:CGRectMake(0, 39, 320, 400)];
[myEventsView willMoveToParentViewController:self];
[self.view addSubview:myEventsView.view];
[self addChildViewController:myEventsView];
[myEventsView didMoveToParentViewController:self];
From the docs:
Each custom view controller object you create is responsible for managing all of the views in a single view hierarchy.
What you are trying to do is to add one viewcontroller's view as a subview of another viewcontroller's view, hence mixing two view hierarchies. That will cause you problems as you have already experienced. Have a look at Carbon Emitter's Abusing UIViewCtrollers article, it gives a thorough explanation and an alternative.
Update
As suggested in the correct answer above, there exists a way to make one UIViewController act as a container for another. From Implementing a Container View Controller (UIViewController Class Reference):
A custom UIViewController subclass can also act as a container view controller. A container view controller manages the presentation of content of other view controllers it owns, also known as its child view controllers. A child’s view can be presented as-is or in conjunction with views owned by the container view controller.
However, this is an iOS >= 5 feature, so my answer will remain correct for applications running iOS versions < 5.
Muncken is right. You cannot add myEventsView.view as a subview to self.view, since myEventsView.view is controlled by its own view controller.
What you probably wanted to do is to add just an new view (that is not controlled by another view controller) as a subview to self.view. So, why don't you just instantiate such a view without a new view controller?
In a project I'm working on, I have the need of a base UI. So i made a baseViewController, made the view in a xib-file and set the baseViewController's view to be the view in the xib-file.
Then I want to inherit that view from the xib-file to my other controllers, but it does not work. Is this impossible? Or have I just missed something?
Example:
//common
playagain = [[game alloc] initWithNibName:#"game" bundle:nil];
//depends on what you use
[[self view] addSubview: [playagain view]];
Use this in other controllers and make sure you import the controller in other controllers... The function is initWithNibName where your nibName goes in.
What I ended up doing was creating a container view controller with a nib, and then adding all other view controllers as child view controllers when it was needed, and removing them when I was done with them. See this tutorial: http://www.cocoanetics.com/2012/04/containing-viewcontrollers/
I think I'm missing something fundamental and so I want to ask the community for some help. I'm building an app based around a basic iPhone Utility Application. My MainView and FlipsideView share some elements so I have created separate ViewControllers and nib files for those pieces. In order to do this I have done the following:
1. Created a viewcontroller called searchDateViewController which is the file's owner of searchDateView.xib
2. searchDateView.xib is basically a UIView with a UILabel inside, the view is wired up correctly
3. Inside both MainViewController.m and FlipsideViewController.m I add a subview as folllows:
- (void)loadView{
[super loadView];
searchDateViewController = [[SearchDateViewController alloc] initWithNibName:#"SearchDateView" bundle:nil];
[[searchDateViewController view] setFrame:[searchDateView frame]];
[[self view] addSubview:[searchDateViewController view]];
...
}
Everything displays and works just fine. Basically depending on actions that happen in each of the main and flipside views the UILabel of the nib is changed. However, I wanted to do something slightly different if the searchDateViewController is loaded from the MainView or the FlipsideView. However, I can't seem to figure out which ViewController is adding the searchDateViewController subview.
In searchDateViewController I tried:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"superview %#", self.view.superview);
NSLog(#"parentviewcontroller %#", self.parentViewController);
}
In both cases I get nil.
So my question is - can I find out which ViewController is adding searchDateViewController a a subview? If so how? Or if my logic here is completely messed up, how should I be doing this?
Thanks!
viewDidLoad is invoked when the view controller has loaded its view. In your case, that happends in this line:
[[searchDateViewController view] setFrame:[searchDateView frame]];
At that moment, you haven't yet called addSubview: so it is no wonder the view's superview is nil.
To solve your problem, you should define a property inside SearchDateViewController to distinguish between the different cases. This property would then be set accordingly by the parent controller that creates the SearchDateViewController instance.
Generally, I do not think it is a good idea to use a UIViewController subclass as a controller for a view that is used as a subview of one or several fullscreen views rather than be used as a fullscreen view itself. Much of UIViewController's logic works on the assumption that it is used to manage a fullscreen view. For instance, with your design, I think it's possible that SearchDateViewController will modify the view's frame when the device orientation changes etc. Since you don't need all this functionality for a non-fullscreen subview, I suggest you subclass your SearchDateViewController directly from NSObject.
ViewController and views are completely separate.
In most cases, when you add a subview to a parent view you don't add its controller to the parent's viewController. The exception to this rule is the navigation controller which adds the controller instead of the view to maintain a hierarchy of view controllers.
Your SearchDate viewController can't find a parent controller because you never assigned one and the system does not do it automatically. You can just assign a parent controller when you evoke the view from another controller.
searchDateViewController.parentController=self;
MyController *myViewController = [[MyController alloc] initWithNibName:#"myView" bundle:nil];
The nib file myView.nib has 2 uiimageviews and 2 uilabels. When I first init myViewController, all the 4 subviews are set as 0x0.
The second time I dont get such a behavior.
The view object itself does not get created until it is referenced via self.view and loadView is called. It could be that the first time you try to inspect the view or do something with it this hasn't happened yet, and the second time could be after the system creates the view if you are adding it to another view or a navigation controller or something.
You probably forgot to hook up the view in your Nib file to the view property of MyController, and/or hooked up the subviews to the various IBOutlets of MyController.
Kevlar is absolutely right. You can force loading view and setting up all references with the following statement:
if (myViewController.view);
It does nothing except you'll get all subviews bound to outlets.
I have a scrollview I'm trying to add ViewControllers to from a nib file.
ViewController *controller=[[ViewController alloc] initWithNibName:#"ViewController" bundle:[NSBundle mainBundle]];
[scrollview addSubview:controller];
Scrollview is defined elsewhere.
Whenever I add other items like UIViews with simple colored backgrounds, that works fine. When I add the ViewController from the nib, the Viewdidload gets hit, the images load from the nib, but then the controller code stops there (No viewWillAppear etc). So I don't get any of the controller's processing.
This same controller works fine when pushed as a nav or tab controller. I'm sure I'm missing something in my educational process, but was hoping someone could help out so I can move on.
BTW: The ViewController above is a simple UIViewController.
I think your issue is that addSubview is expecting a UIView not a UIViewController - you probably get a warning when compiling ('may not respond to selector' or similar?). If so, don't just ignore those - in my experience, usually they are a problem in your code :-)
You could try something like
[scrollview addSubview:controller.view];
But this still won't get you the viewcontroller's processing ...you need to do that processing in the view controller that has the scrollview AFAIK. I would suggest trying to get a basic view with a scrollview working in IB first.
OK, seems a little off, but I added viewWillAppear to viewDidLoad, and that worked, but this doesn't seem the right way to do it, correct?