rootViewController and addSubview in Objective-C? - ios

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.

Related

How did iOS set UIViewController's view frame before shown?

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.

Present modal ViewController from SubView

I am trying to present a modal view controller C from view controller B. B's view does not cover the full screen, and is a subview of another view controller, A. What I am seeing when I try to present a fullscreen modal is the modal is covering the full screen, but when I tap on certain places in the screen the control will get 'passed through' to A's view.
I can bypass this by presenting the modal from A via some kind of delegation, but I have no idea why this is happening! After all, if you have a tab bar controller managing one of your views, and you try to present a modal view, it covers the full screen just fine. Is there some magic going on behind the scenes?
I don't think there is any official documentation on how the modal is implemented, but any view can get the UIWindow of the UIApplication and call -presentModal... on the rootViewController property. This will have the affect of making your modal full screen. I'm sure there are other ways of achieving the same effect though.
[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentModalViewController:myModalVC animated:YES];
In that scenario, you need to implement your own 'modal' methods for all your view controllers, using addSubview: and bringSubviewToFront:. I've done this in one of my larger project where I wanted some different behavior from the modal views.
This worked for me:
UIViewController* vc = [[[UIViewController alloc] init] autorelease];
UIWindow* keyWindow = [[UIApplication sharedApplication] keyWindow];
UIView* topView = [[keyWindow subviews] objectAtIndex:[[keyWindow subviews] count] - 1];
vc.view = topView;
[vc presentModelViewController...
Basically, you create a new UIViewController and attach it to the topmost view on the main window (which is the view the user currently sees).
Simple, but not sure about acceptance and efficiency. This is what I use.
Embed all the view controllers in a mainView below the rootView.
Add any modal views to the rootView while disabling userInteractionEnabled flag for the mainView. The modal view should be added to rootView and not mainView
Once done, re-enable the user interaction for mainView.
Hope this helps...

Losing rotation support after programmatically adding UITabBarController to UIWindow

My application starts off with nothing but a UIWindow. I programmatically add a view controller to self.window in application:didFinishLaunchingWithOptions:.
myViewController = [[UIViewController alloc] init:...];
...
[self.window addSubview:myViewController.view];
[self.window makeKeyAndVisible];
At the same time i kick off a background process:
[NSThread detachNewThreadSelector:#selector(startupOperations) toTarget:self withObject:nil];
The startupOperations look something like this:
NSAutoreleasePool *threadPool = [[NSAutoreleasePool alloc] init];
// Load data
...
// When your done, call method on the main thread
[self performSelectorOnMainThread:#selector(showMainViewController) withObject:nil waitUntilDone:false];
// Release autorelease pool
[threadPool release];
showMainViewController removes myViewController, creates a UITabBarController and sets it as the window's main view:
[self.myViewController.view removeFromSuperview];
self.myViewController = nil;
tabBarController = [[UITabBarController alloc] init];
...
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
Questions:
All the view controllers are returning YES for shouldAutorotateToInterfaceOrientation:. Rotation works fine for myViewController but as soon as the tabBarController is made visible, rotation stops working and interface appears in Portrait. What's the reason behind this behavior?
Also, in iOS 4.x, UIWindow has rootViewController property. What's the role of this property? The new templates use rootViewController instead of [self.window addSubview:...]. Why is that?
Pretty strange. I tried and simulate your "view flow" in a simple tab bar based project and autorotation effectively works after removing the initial controller and adding the tab bar controller's view as a subview.
The only condition I found where it did not work is when self.window did contain a second subview that I did not remove. Could you check at the moment when you execute
[self.window addSubview:tabBarController.view];
what is self.window.subview content?
If that does not help, could you share in your question how you initialize the UITabBarController and UITabBar?
As to your second question, as you say rootViewController is the root controller for all the views that belong to the window:
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.
(Source)
You can also use that, but take care of assigning it already in applicationDidFinishLaunching, otherwise, if you "manually" add a subview and later change this property, it will not remove the subview you explicitly added.

UIView: adding UIViewController's view as a subview and its removing

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).

How can I replace a UIViewController with a UISplitView Controller?

Mine is a normal viewcontroller application. When I click a button on this mainView, it adds a 2nd view(a different xib) as a subview to the mainView. I want this 2nd view to be replaced by a splitview. So it means I should replace the 2nd view controller with a UISplitViewController, isnt it?
Can I do that? Is it possible to add a splitviewcontroller's view like v add a viewcontroller's view?
You should be aware that, currently, the only official usage of UISplitViewController is as a root view controller of an application; Apple does not intend for it to be a child view controller. Apparently, this is due to bugs with handling rotation of the iPad, and may get fixed at a later date. So you should avoid adding a UISplitViewController's view as a subview to anything.
You can subclass UIViewController and then in the init:
UIViewController *left = ...;
UIViewController *right = ...;
UISplitViewController *splitVC = ...;
splitVC.viewControllers = [NSArray arrayWithObjects:left,right,nil];
self.view = splitVC.view;
return self;
Then just use this as a normal UIViewController.

Resources