I am getting a height of 656 in my viewDidAppear on a view controller. This is not the correct height that I am expecting from an iPhone 5. Any idea why this might be happening? I have a UIView that I added as a subview of this UIViewController and I set the struts such that it will always stick to the bottom of the UIViewController. However because the height is 656, I can no longer see this UIView. ANy idea why?
Here's my code:
- (void) viewDidAppear:(BOOL) animated
{
[super viewDidAppear:animated];
NSLog(#"%f", self.view.bounds.size.height);
}
This is how I am initializing the VC:
SavedViewController *savedStoriesVC = [[SavedViewController alloc] initWithNibName:#"SavedViewController" bundle:nil];
savedStoriesVC.managedObjectContext = managedObjectContext;
savedStoriesVC.delegate = self;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:savedStoriesVC];
navController.navigationBarHidden = YES;
I just had this same problem. I was able to "fix" it by turning off all of the struts and springs. But then, of course, rotations didn't work.
Related
I have page-based app. On each page I have 3 uibuttons at the top, uiscrollview with alphabet (uibuttons to sort data in uitable) at the right and uitableview at the center. How to show cell's detail view? If it is necessary to add uinavigationcontroller I can't do this. If I adds it, it disables interaction with my table, buttons and scrollview.
And another question is how to show new data in tableview and scrollview when goes to next page??
I have rootViewController class and DataViewController class.
rootViewController listing:
#interface RootViewController ()
#property (readonly, strong, nonatomic) ModelController *modelController;
#end
#implementation RootViewController
#synthesize pageViewController = _pageViewController;
#synthesize modelController = _modelController;
#synthesize navContr = _navContr;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Configure the page view controller and add it as a child view controller.
//[self presentModalViewController:navContr animated:YES];
self.pageViewController = [[[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil] autorelease];
self.pageViewController.delegate = self;
DataViewController *startingViewController = [self.modelController viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = [NSArray arrayWithObject:startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
self.pageViewController.dataSource = self.modelController;
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
self.navContr = [[UINavigationController alloc] initWithRootViewController:self.pageViewController];
[self.view addSubview:self.navContr.view];
// Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
CGRect pageViewRect = self.view.bounds;
self.pageViewController.view.frame = pageViewRect;
[self.pageViewController didMoveToParentViewController:self];
// Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
for (UIGestureRecognizer *recognizer in self.pageViewController.gestureRecognizers){
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]){
[recognizer setEnabled:NO];
}
}
}
After few manipulations it works but I need help to get it work fine!
So now it looks like this
Next question: how do I remove the brown space at the top???
::UPDATE::
Problem solved. It needs just to set y-axis position of UINavigationController to -20 ;)
i'm not sure if this link about creating navigation-based project may help you.. (http://iosmadesimple.blogspot.com/2012/08/navigation-based-project-doing-it.html)
From that tutorial, there's a class called SampleViewController, subclass of UIViewController. You might want to put a tableView in SampleViewController.xib file. Then in your SampleViewController.h file, add an IBOutlet UITableView* yourTable property and synthesize it. Connect it to your tableView in your .xib file. //Or you may do it programmatically
in your SampleViewController.h, make your interface header look like this.. I think you already know this...
#interface SampleViewController:UIViewController < UITableviewDelegate, UITableViewDatasource >
in your SampleViewcontroller.m, under viewDidLoad method, set the table delegate and datasource to self:
yourTableView.delegate = self;
yourTableView.datasource = self;
Afterwhich, you implement tableView delegate and datasource methods... //you already know those since you were already able to show a tableview ;)
one of these methods is the "tableview:didSelectAtIndexpath:" --> this is the part wherein you can put your code when you click one of the cells.
Let's assume you have the DetailsViewController Class, this is the class you would like to show after clicking a cell and show its details.
DetailsViewController Class must have a variable that will accept the data you would like to show. Let's say, an NSString *detailsMessage; //do the #property and #synthesize thing...
Let's go back to SampleViewController.m file, under tableview:didSelectAtIndexpath: Method:
inside that Method.. put these codes.
DetailsViewController *detailsVC = [[DetailsViewController alloc] init];
detailsVC.detailsMessage = #"The Data you want to pass.";
[self.navigationController pushViewController:detailsVC animated:YES];
I hope this helps. :(
There may be other ways but by far the easiest way is to use a navigation controller. In fact, it is built to do exactly this.
If you don't want the navigationBar then you can hide it in the viewWillAppear function.
[self.navigationController setNavigationBarHidden:YES animated:YES];
Then you can add an other UIViewController to push when the user selects a cell.
Having read your OP again I'm not sure how you are adding your navigationController.
To use a navigationController you create it and load it at start time. You then create your current viewController (the one with the buttons and table etc...) and set this as the rootViewController of the navigationController.
Then you display the navigationController.
Could you explain how you are adding your navigationController as it may help understand what is going wrong.
Thanks
::EDIT::
OK, my assumption was correct.
The way you are using the navigation controller is not how it was intended.
OK, so at the moment your AppDelegate file will have a method Application didFinishLaunching...
It will look something like this...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[OJFViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
You should change it so that it is like this...
first add a property to your appDelegate...
#property (nonatomic, strong) UINavigationController *navigationController;
Then change the didFinishLaunchingMethod to this...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[OJFViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
This will still show you MainViewController but it will now be contained within a navigationController.
Next in your MainViewController function viewWillAppearAnimated add the line...
[self.navigationController setNavigationBarHidden:YES animated:animated];
This will then hide the navigationBar at the top of the view so you still have access to your buttons.
The you need a new ViewController and xib file (for example DetailViewController).
When the user selects a table row you need to then do something like...
DetailViewController *detailView = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
//pass in details of which row was selected.
[self.navigationController pushViewController:detailView animated:YES];
This will then display your new view and new viewController. You will also need to write a way of passing the data in (set up a property on the DetailViewController).
Hope this helps.
In my App I use a UITabbarController, which rotates perfectly to all UIInterfaceOrientations in all viewcontrollers. But when I add an UIView to the UIWindow afterwards it will not be added in the current UIInterfaceOrientation, but always in UInterfaceOrientationPortrait (which is default for the app). It won't rotate to a new orientation also. I add the ViewController by using:
LoginViewController *loginViewController = [[LoginViewController alloc] init];
[self.window addSubview:[loginViewController view]];
I have
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
NSLog(#"%#", #"YES IT WILL!");
}
in LoginViewController.m but there will never be logged anything. Any idea why the subview won't rotate?
SideSwipe
EDIT:
Found the solution:
Apparently UIWindow should only have one subview, not more, otherwise things will mess up, so i call:
LoginViewController *loginViewController = [[LoginViewController alloc] init];
[tabBarController presentModalViewController:loginViewController animated:YES];
instead, which will autorotate the loginviewcontrollers view just fine.
I have a view inside another view, when rotation happened, only the parent willRotateToInterfaceOrientation got called, so what I did is add [self.subViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; to parent's willRotateToInterfaceOrientation method.
As you are adding a new subview to window, you have to make the window rotate too.
Hi i have a splitViewController
mapViewController = [[MapViewController alloc] initWithManagedObjectContext:managedObjectContext startingRegion:startingRegion];
distanceViewController = [[DistanceTableViewController alloc] initWithManagedObjectContext:managedObjectContext];
distanceViewController.mapViewController = mapViewController;
setupViewController = [[SetupTableViewController alloc] initWithStyle:UITableViewStyleGrouped map:mapViewController.map];
setupViewController.positionSwitch.on = savePosition;
SearchTableViewController *searchViewController = [[SearchTableViewController alloc] initWithStyle:UITableViewStylePlain managedObjectContext:managedObjectContext];
searchViewController.mapViewController = mapViewController;
tabBarController = [[UITabBarController alloc] init];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
UINavigationController *mapNavigationController = [[[UINavigationController alloc] initWithRootViewController:mapViewController] autorelease];
UINavigationController *searchNavigationController = [[[UINavigationController alloc] initWithRootViewController:searchViewController] autorelease];
UINavigationController *distanceNavigationController = [[[UINavigationController alloc] initWithRootViewController:distanceViewController] autorelease];
UINavigationController *setupNavigationController = [[[UINavigationController alloc] initWithRootViewController:setupViewController] autorelease];
UISplitViewController* splitVC = [[UISplitViewController alloc] init];
splitVC.viewControllers = [NSArray arrayWithObjects:searchNavigationController, mapNavigationController, nil];
splitVC.title = #"iMetano";
splitVC.tabBarItem = [[[UITabBarItem alloc] initWithTitle:#"Mappa" image:[UIImage imageNamed:#"mapIcon2.png"] tag:0] autorelease];
NSArray *viewControllersArray = [NSArray arrayWithObjects: splitVC,setupNavigationController,nil];
[splitVC release];
tabBarController.viewControllers = viewControllersArray;
}
When i startup my app in portrait, all works fine.
When i startup my app in landscape this is the result
I see only the view of the first viewController SearchTableViewController with some pixel between the UINavigationController and the status bar
When i rotate in portrait and after i return in landscape i see both viewController's view, but the second have some pixel between the statusBar and the UINavigationControllor
I can't understand why.
apple says not to put a split view controller inside something else, like a tab bar controller
After looking at my code and IB time after time. This is the best that I could come up with. Not sure if is the best one but it works for me. Im loading a default detail view controller. If I load the controller directly in the viewDidLoad then the problem occur. If I load it from the selector the problem goes away. I hope this helps. I have this code in the RootViewController.
- (void)viewDidLoad {
[super viewDidLoad];
[self performSelector:#selector(loadController) withObject:nil afterDelay:0];
}
-(void)loadController{
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
WebViewController *newDetailViewController = [[WebViewController alloc] initWithNibName:#"WebViewController" bundle:nil];
[newDetailViewController setTitle:#"Home"];
NewNavController <SubstitutableDetailViewController>*navController = [[NewNavController alloc] initWithRootViewController:newDetailViewController];
detailViewController = navController;
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
}
I had this exact same problem when attempting the combination of tab bar, split view and navigation controllers. I noticed that the alignment gap is only present when the application first fires up and the first tab is auto-selected because it's the first tab in the tab bar controller's array of view controllers. After switching tabs and then coming back to the one with the misaligned nav controller in a split view, there was no alignment problem present. So, to replicate this behavior and get rid of the misalignment when the screen is first rendered I added:
[tabBarController setSelectedViewController:splitVC];
right after setting the view controller array on the tab bar controller. Works like a champ now.
I know this is an old question, but here's the hack I just used to get around this problem for anyone who has a navigation hierarchy like mine:
UITabBarController
Tab0->UINavigationController->MGSplitViewController _or_ UISplitViewController
Tab1->UINavigationController->SomeOtherViewController
Tab2->Etc...
Nothing I tried could get rid of that 20px gap that occurs only once, at bootup, if the device orientation is anything except UIInterfaceOrientationPortrait. The 20px gap is caused by the UINavigationBar for the split view's UINavigationController above having a non-zero origin.y value; most likely, you'll find it to be 20.
Also, I found that this is only a problem if the device is running iOS < 5.0.
I check for this issue in the view controller code of my MGSplitViewController (i.e. self = an MGSplitViewController):
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if(self.doIOS4OneTimeRotationHack == YES)
{
self.doIOS4OneTimeRotationHack = NO;
for(UINavigationController *navController in [self viewControllers])
{
if(navController.navigationBar.frame.origin.y != 0.0f)
{
[UIView animateWithDuration:0.01
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:
^(void)
{
navController.navigationBar.frame = CGRectMake(navController.navigationBar.frame.origin.x,0.0f, navController.navigationBar.frame.size.width,navController.navigationBar.frame.size.height);
}
completion:
^(BOOL finished)
{
//NSLog(#"Shifted navbar 0x%x up!",navController.navigationBar);
}];
}
}
}
}
With the animation set to finish in just 0.01 seconds, it happens so fast that you'll never even notice it as your bootup splash screen disappears and your MGSplitViewController view appears in its place. Maybe play around with it and make it instantaneous; I had to get it working and move onto my next task, so I didn't fool with it past that point.
I don't like resorting to hacks like this, but this was the only way I was able to get around this problem. ScottS' solution below sounded great, but unfortunately didn't work for me.
I wanted to create a very simple method that switches between views in a view based application. For some reason, when the views are switched, the first view is removed and instead of viewing the second view, I see a white screen.
This is my method:
FirstViewController *firstViewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
self.view = firstViewController.view;
[firstViewController.view removeFromSuperview];
[firstViewController release];
secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.view = secondViewController.view;
I don't know why it is happening because I know that the second view's ViewDidLoad method is called (I put a NSLog there) - but the second view is not seen!
Any suggestions?
Thanks in advance,
Sagiftw
viewDidLoad's executing because initWithNibName:bundle: calls it. That doesn't mean that the view's actually being displayed.
I usually use this (removing initialisation/release logic):
[self.view addSubview: firstViewController.view];
[firstViewController.view removeFromSuperview];
[self.view addSubview: secondViewController.view];
I'm having a strange problem with adding a UINavigationController to my iPhone application. I add the controller as follows:
myViewController *viewController = [[myViewController alloc] initWithNibName:#"myView" bundle:nil];
myNavigationViewController *navigationController = [[myNavigationViewController alloc] initWithRootViewController:viewController];
UIView *finalView = myeNavigationViewController.view;
[self.view addSubview:finalView];
All seems to work as planned except I get a weird white space at the top of my view between the status bar and the UINavigationController title bar.
alt text http://www.andrewskinner.name/problem.png
I've searched online but don't really know what to search for. Has anyone else had this problem? Can you point me in the direction of some help?
Thanks in advance.
What does the line
UIView *finalView = myeNavigationViewController.view;
add to the code? It's redundant as you can add the view directly without assigning it to a UIView first - plus it's incorrect as it references the myNavigationController and not navigationController..
I tend to do this
myViewController *viewController = [[myViewController alloc] initWithNibName:#"myView" bundle:nil];
myNavigationViewController *navigationController = [[myNavigationViewController alloc] initWithRootViewController:viewController];
[navigationController.view setFrame: [self.view bounds]];
navigationController.delegate = self;
[self.view addSubview:[navigationController view]];
Setting the frame to the bounds also removes the white space at the top you were asking about.
Check out the answers in this question:
Not sure why UIView is being nudged up by around 10px
The issue is that UINavigationController ideally should be the direct subView of UIWindow. It will position and size right by itself. When you add UINavigationController into another custom view of a UIWindow subview, you need to take care of the position and size of this custom view by taking into account whether the status bar is shown or not in the UIWindow.
My suggestion is to make the custom view as a subclass of UINavigationController:
mySubClass_NavigationController*nav=[[mySubClass_NavigationController alloc] initWithRootViewController:viewController ];
[myUIWindow addSubview:nav.view];
and inside the mySubClass_NavigationController, you can do all the customization that you are doing now in your self (whatever that controller is).
I struggled with this for a while too using very similar code to the op's and also had a white bar above my navigation controller.
My problem occurred when adding the UINavigationController as a view in a UITabController. The space in my case was caused by the UINavigationBar part of the UINavigationController taking into account the status bar and it was actually overlapping part of the view that I was trying to show in the UINavigationController.
This is the code I ended up with in loadView in one of my UITabBarController view controllers.
SomeUITableViewController *screenList = [[SomeUITableViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:screenList];
CGRect frame = [[navController navigationBar] frame];
frame.origin.y = 0; // Was 20, set to 0 to not take into account the status bar.
[[navController navigationBar] setFrame:frame];
[self setView:[navController view]];
There's some more information at http://discussions.apple.com/message.jspa?messageID=7890362.
There is an obscure property in IB called "Hides Bottom Bar on Push". Just check it. It solved the problem for me.
Maybe you have somehow gotten yourself two UIViews,
each with a status bar. Check the xib.