I would like to ask what is the correct way to add and remove UIViewController's view as a child view.
So, having UIViewController initialized I can add its view to view hierarchy as follows:
UIViewController *myViewControler = [[UIViewController alloc] init];
[someAnotherView addSubview:myViewController.view];
Question 1: Should I release myViewController.view after addSubview: call?
If I want to remove myViewController's view from view hierarchy I call [myViewController.view removeFromSuperview];
Question 2: How should I release myViewController instance in this case after its view removedFromSuperview?
You do not need to release the view, the owning view controller will do this for you.
I normally put the declaration of myViewController in the header and then release and nil it when I am done with it (either somewhere in the normal flow or in the dealloc of the containing view controller).
Related
Im starting to learn OC.
The first question is about _window.rootviewcontroller and [_window addSubview:...]
Both of the two ways can set view for UIWindow (actually, UIWindow is inherited from UIView).
So what I want to know is :
Is setting the rootviewcontroller for window just using the addSubview method to implement , or it's something else?
more exactly:
is
_window.rootviewcontroller = viewController;
meaning
[_window addSubview: viewController.view];
or
_window = viewController.view; //UIWindow : UIView
or something else?
Thanks a lot.
Is there anyone who can tell me some details about UIWindow and the rootViewController property?
If you use addSubview: to have to pass a UIView instance but when you call rootviewcontroller you passing UIViewController instance to the UIWindow.
You can use addSubview but you have to associate UIView superview (Which needs to be UIViewController) to the UIWindow, to make it behave the same,
something like that (old way to to that:
[window addSubview:myViewController.view];
[window makeKeyAndVisible];
By using rootviewcontroller it will do it for you.
This is taken from Apple:
The root view controller provides the content view of the window.
Assigning a view controller to this property (either programmatically
or using Interface Builder) installs the view controller’s view as the
content view of the window. If the window has an existing view
hierarchy, the old views are removed before the new ones are
installed.
Obviously not. The root view controller is generally assigned to window in appdelegate class.
Also, root view controller is always associated with UINavigationController. So that any root view controller of a UINavigationController will be a its content view controller.
Where as, add subview is just a method of UIView class. Which helps to add any subview to the respective view.
I am developing an app in which a UIViewController (firstViewController) contains some UILabels, a UIButton, and a UIView (subView). The UIView should display the UIViewController (secondViewController) that contains some layers. I am unable to do this.
What should I do to display secondViewController within subView of firstViewController?
You should use UIViewController containment or parent/child view controllers. You can read details here.
The most basic version is:
UIViewController *parentVC = ...
UIViewController *otherVC = ... // it's view will be added as subview
[parentVC addChildViewController:otherVC];
[parentVC.containerView addSubview:otherVC.view]; // containerView is a view where your child view controller should go
[otherVC didMoveToParentViewController:parentVC];
If you only add other view controller's view as a subview, child view controller won't receive all the events. For example, if you use other methods suggested here (just add view as subview and nothing more), you won't get -viewDidAppear: message (and others) sent to your child view controller.
You can do that by adding view of another view controller as sub view in view as bellow
SecondVC *aObjSecondVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondVC"];
[self.view addSubview:aObjSecondVC.view]
You can add it using the following line:
[self.subView addSubView:secondViewController.view];
I got a view controller named IntroViewController in my storyboard and I want to add this as a child to another view controller like this:
IntroViewController *introViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"View1"];
[introViewController.textLabel setText:#"test"];
[self addChildViewController:introViewController];
On the IntroViewController I've put a label named textLabel on it in the storyboard, if I run the program it works and shows me the view controller, but the text doesn't get changed. Any idea how I can fix this?
When you instantiate a view controller from a storyboard, the view is not loaded until it is actually presented on screen. At the point in your code you have posted introViewController.textLabel is nil.
One option you could do is add a property to your IntroViewController class and instead set that:
introViewController.initialText = #"test";
Then, inside -viewDidLoad of your IntroViewController the label will be instantiated so you can make the call:
[self.textLabel setText:self.initialText];
It is also worth noting that most of the time it would be recommended to have a view controller be the one to set values on the views it owns, rather than some other view controller.
I am not familiar with iOS UIViewController's detail implement. I have the following code to create a new UIViewController and show it, but the frame I set during initWithFrame method does not worked, the controller's view always is fullscreen(320*480).
UIViewController *viewController = [[UIViewController alloc] init];
// view
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 140, 130)];
viewController.view = view;
[view release];
AppController *app = (AppController*)[[UIApplication sharedApplication] delegate];
UINavigationController *nav = [app navController];
[nav pushViewController:viewController animated:YES];
[viewController release];
I search releative thoughts in apple developer documents, but I found nothing useful for this. How did UIViewController deal with its view frame property before show it? Where can I found useful documentation.
Thank you.
Update: In fact, the code is from cocos2d-iphone DirectorTest: https://github.com/cocos2d/cocos2d-iphone/blob/release-2.0-rc1/tests/DirectorTest.m#L143
You've got this all wrong - you really need to read (and understand) Apple's UIViewController docs:
View Controller Catalog
View Controller Programming Guide
View Controller Reference
If you're creating a view in code for a view controller, you should do it in the view controller's loadView method.
Directly from Apple's documentation:
Creating a View Programmatically
If you prefer to create views programmatically ...
you do so by overriding your view controller’s loadView
method. Your implementation of this method should do the following:
Create a root view object. The root view contains all other views
associated with your view controller. You typically define the frame
for this view to match the size of the app window, which itself should
fill the screen. However, the frame is adjusted based on how your view
controller is displayed. See “View Controller View Resizing.”
You can use a generic UIView object, a custom view you define, or any
other view that can scale to fill the screen.
Create additional subviews and add them to the root view. For each
view, you should do the following:
Create and initialize the view. For system views, you typically use
the initWithFrame: method to specify the initial size and position of
the view. Add the view to a parent view using the addSubview: method.
Assign the root view to the view property of your view controller.
I have a main view which has a UISlider on it.
From the main view I add a subview using:
gameView *myViewController = [[gameView alloc] initWithNibName:#"gameView" bundle:nil];
[self.view addSubview:myViewController.view];
The subview is created on top of the main view.
When I remove the sub view using:
[self.view removeFromSuperview];
the main view underneath becomes visible.
I want to be able to update the value of the UISlider on the main view, from the sub view, before I call [self.view removeFromSuperview]
Is it possible?
Basically the question can be generalized to how to update an IBOutlet on the main view from the sub view.
Help is greatly appreciated.
Many thanks!
Yes, it's possible.
And there's a few ways to do this. Here's how I would do it:
First, make your parent view controller's UISlider a property that can be accessed by other objects.
Secondly, give your gameView object an instance variable that you'll link to the parent view (let's call it id savedParent;)
Then, before you do removeFromSuperview, you can simply do something like:
ParentViewController * parentVC = (ParentViewController *) savedParent;
if(parentVC)
{
// some float value of whatever you want to set the slider value to
parentVC.slider.value = 0.5f;
}
Also, why are you instantiating a whole View Controller object (gameView) if you simply want to add a subview? When you do your removeFromSubview call, the view gets removed but your gameView view controller isn't released (and might even be getting lost & leaked in memory, leading to a crash). If you want to do a subview, subclass UIView. If you want to push a new view controller, push the whole controller (and not just the view it contains).
Here is another way:
I'm not sure what the slider is representing, but you need to create an object that represents this
#interface MyGameThing : NSObject
#property (assign) CGFloat myValue;
#end
#implementation MyGameThing {
CGFloat *_value;
}
#synthesize myValue = _myValue;
#end
You then need to pass that object to both of your view controllers (or make it a singleton).
Then, on ParentViewController, in the viewWillAppear, just set the slider to the new value.
Daniel.
(p.s. don't just add view controllers views to the superview, use presentModalViewController / dismissModalViewController or a navigation controller).