What exactly is navigationController.view.superview? - objective-c

My project has existing code in several places where it uses navigationController.view.superview.frame and navigationController.view.superview.center to size and center modal views on top of current view. Sure I can use them as boiler plates but honestly I have no idea what navigationController.view.superview really refers to. Is it particular to UINavigationControllers? Any ideas/comments would be appreciated.
[Edit] Here's the code:
UIStoryboard *sb = self.storyboard;
MyViewController *vc = (MyViewController *)[sb instantiateViewControllerWithIdentifier:#"MyLoginViewController"];
vc.delegate= self;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc];
navController.modalPresentationStyle = UIModalPresentationFormSheet;
[self.navigationController presentModalViewController:navController animated:YES];
navController.view.superview.frame = CGRectMake(
navController.view.superview.frame.origin.x,
navController.view.superview.frame.origin.y,
400.0f,
400.0f
);
navController.view.superview.center = self.view.center;
If I don't use navigation controller for the new modal view, I wouldn't have to use "superview". Namely,
UIStoryboard *sb = self.storyboard;
MyViewController *vc = (MyViewController *)[sb instantiateViewControllerWithIdentifier:#"MyLoginViewController"];
vc.delegate= self;
[self.navigationController presentModalViewController:vc animated:YES];
vc.view.frame = CGRectMake(
vc.view.frame.origin.x,
vc.view.frame.origin.y,
400.0f,
400.0f
);
vc.view.center = self.view.center;
However, I wouldn't be able to view the presenting vc in the background...

navigationController - This is, well probably a UINavigationController. I say probably because you've not given any context so I can only assume that from the name.
navigationController.view - The navigation controller's view.
navigationController.view.superview - The navigation controller's view's superview. i.e. the view that the navigation controller's view sits in.
navigationController.view.superview.frame - The navigation controller's view's superview's frame. i.e. the frame (position and size) of the view the navigation controller's view sits in.
navigationController.view.superview.center - The navigation controller's view's superview's centre. i.e. the centre (position of the centre point) of the view the navigation controller's view sits in.
It's ugly to use these properties directly like that. I can't conceive of why you would want to ever go hunting into the depths of the view hierarchy like that to do anything. This to me is a bad smell. I suggest finding the right way of solving the problem.

In most cases, that probably refers to your instance of UIWindow. If you're trying to center things on screen, you can get the rect of the device's screen using [UIScreen mainScreen].applicationFrame.

As explained in the documentation for UIView, the method -superview returns the view's superview in the view hierarchy. That is, the superview is the view that contains the navigation controller's view. This is not specific to UINavigationController.

Related

Flip landscape UIViewController

I have a button in my UIViewController, I want to have Flip transaction when I press the button, I have transaction but it's flip portrait, would you please help me!
I want to have it as Landscape
here is my code :
TestViewController *ctrl = [[TestViewController alloc] init];
[UIView transitionFromView:self.view
toView:ctrl.view
duration:1
options:UIViewAnimationOptionTransitionFlipFromTop
completion:nil];
[self.navigationController pushViewController:ctrl animated:NO];
Thanks in advance!
What you're doing is illegal in any case. You may not transition your own view (self.view) out of the view hierarchy. Either transition a subview of self.view to a different subview of self.view, or else, if you want to use views belonging to view controllers, set up a system of parents and children and manage them properly (and, in general, call transitionFromViewController:toViewController:duration:options:animations:completion:).
If what you're trying to do is summon the view of a different view controller, then use one of the methods that does that, such as presentViewController:animated:completion:.

Is this the right way to add a view?

I make a program that shows a table.
If people click the search I will add another view covering the original view. The original view is [BNUtilitiesQuick listnewcontroller];
[[BNUtilitiesQuick window] addSubview:[BNUtilitiesQuick searchController].view];
[[BNUtilitiesQuick searchController] viewWillAppear:YES] is indeed called. So it seems that UIView has a pointer to it's controller
However, the view that the [[BNUtilitiesQuick listnewcontroller] viewWillDisappear] is not called
Moreover, [[BNUtilitiesQuick listnewcontroller] viewWillAppear] is also not called even when the user has finished modifying search term with this code:
[self.view removeFromSuperview];
I think I may be missing something here. What exactly should I do anyway so IOs knows that the searchController.view will be covering listNewController?
This is NOT the right way to do it. If the searchController is a full screen controller you should present it modally using presentViewController or push it onto the navigation stack as #StuR suggested.
In case your search view covers only part of the listnewcontroller you should use the containment API in iOS5.
Inside listnewcontroller (parent view controller) you would write:
[self addChildViewController:self.searchController];
[self.view addSubview:self.searchController.view];
[self.searchController didMoveToParentViewController:self];
For more in-depth information check out the WWDC 2011 session video "Implementing UIViewController Containment". Also watch "The Evolution of View Controllers on iOS" from 2012 because there are some changes and deprecations in iOS6.
ViewController *viewController = [[ViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
I'd consider using pushViewController for adding a full screen view. addSubview is for views that don't cover the entire screen.
viewWillDisappear and viewWillAppear will only me called if you pop or push the given viewController. You are simple adding a subview with it's own viewController inside(on top) of the present viewController. As StuR said, if you want to dismiss the current ViewController you should use:
BNUtilitiesQuick *searchController = [BNUtilitiesQuick alloc] init];
[self.navigationController pushViewController:searchController animated:YES];
You can read more about ViewControllers here: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007457

Ensuring that a UIViewController is fully set up before loadView is called

There is a UIViewController that uses a UIImageView, and that image view is initialized with image data (NSData). It does not use a XIB, but creates its view programmatically:
- (void)loadView
{
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData:self.imageData]];
scrollView = [[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
scrollView.contentSize = imageView.bounds.size;
scrollView.delegate = self;
[scrollView addSubview:scrollView];
}
That data has to be set by another controller which allocs, inits, and pushes this view controller onto the navigation controller:
ImageViewController *imageViewController = [ImageViewController alloc] init];
imageViewController.imageData = someData;
[self.navigationController pushViewController:imageViewController animated:YES];
How do I know that everything that needs to be done, which in this case, is setting the data, is done before loadView is called? Or, do I not know, and I have to create a custom initializer, or somehow call loadView again when the view controller receives the data?
I have faced many similar situations where I was confused about what will happen, such as with UITableViewControllers.
How do I know that everything that needs to be done, which in this case, is setting the data, is done before loadView is called?
Because the documentation mentions that view controllers do not load their views until they are needed. And the view controller's view is not needed before the navigation controller tries to push it on screen.
Besides, the proper place for assigning the imageData to your image view is probably viewDidLoad ("If you want to perform any additional initialization of your views, do so in the viewDidLoad method."). And your loadView method will not do anything visible in its current form. You have to assign a view to the view controller's view property in that method.
loadView will happen when the view property of the view controller is accessed. The code you wrote will work fine, because the first time the view property will be accessed will be somewhere inside pushViewController.
If you wrote this you'd have a problem:
ImageViewController *imageViewController = [ImageViewController alloc] init];
NSLog(#"size = (%.0f, %.0f)", imageViewController.view.frame.size.width,
imageViewController.view.frame.size.height);
imageViewController.imageData = someData;
[self.navigationController pushViewController:imageViewController animated:YES];
because you access the view property in the NSLog. That would cause loadView to get called before imageData was set.

presentModalViewController ontop of subview?

I am trying to recreate the iPhone's tabView, but with my own style, buttons, etc. I didn't want to have to totally redo my app, so I simply added a view to the bottom like this [window addSubview:theToolbar]; theToolbar.frame = CGRectMake(0, 425, 320, 44); in my appDelegate.
However, when trying to do this from a view inside a navigationController theToolbar is over it. Is there anyway to somehow present it to the front?
Here's my code to present the view:
AppSettingsController *appSettings = [[AppSettingsController alloc] initWithNibName:nil bundle:nil];
appSettings.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:appSettings animated:YES];
[appSettings release];
Thanks.
it's impossible show partial views of the viewcontroller. if your want to use the same toolbar, you should retain the toolbar to your appdelegate, and add the toolbar to each viewcontroller when it is in view.
or you should just use uiview's as viewcontrollers

UINavigationController with UIView and UITableView

I'm creating a navigation-based app which displays a graph, rendered with openGL, and a tableview listing disclosure buttons of all of the elements that are displayed on the graph, and a settings disclosure button.
The navigation controller is also a tableview delegate and datasource, and the tableview is added to the view programatically and has its' delegate and datasource set to 'self'. The OpenGL based graph view is added via IB.
The problem I'm having is that I'm trying to push a view controller (either settings or graph element properties) within the didSelectRowAtIndexPath method. The method registers and the new view is pushed on, but the tableview stays and obscures part of the view that was pushed on, as if it has a different navigation controller.
I can't seem to set the tableview's navigation controller to be the same as the rest of the UINavigationControllers' view.
Does anyone know how I could fix this?
My navigation controllers' initWithCoder method, where the tableview is added, appears as follows:
elementList = [[UITableView alloc] initWithFrame:tableFrame style:UITableViewStyleGrouped];
elementList.dataSource = self;
elementList.delegate = self;
[self.view addSubview:elementList];
Further in the source file, the DidSelectRowAtIndexPath method where the navigation controller is pushed appears as follows:
Settings* Controller = [[Settings alloc] init];
[self pushViewController:Controller animated:YES];
[Controller release];
Fixed by just adding a UITableView in IB, adding IBOutlet to elementList, and setting the UIViewController as the delegate and datasource via IB.
Stack Overflow can be really useful for putting your problems to words so the solution becomes obvious.