I am writing a universal application. As a result I have set it up so that my XIB/NIBs are not created with the view controllers, but are created separately and then linked to the view controller by setting the Class Name on the XIB to that of the appropriate view controller (and linking the view on File's Owner to the view on the XIB). I then load the appropriate XIB/NIB (iPhone or iPad) when the view controller is initialized, like so:
SomeViewController *vc = [[SomeViewController alloc] initWithNibName:@"SomeView-iPhone" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
Additionally, the iphone version is setup with a UITabBarController at the bottom and a UINavigationController at the top. That is created like this:
MyAppDelegate *appDelegate = (MyAppDelegate *)[UIApplication sharedApplication].delegate;
UINavigationController *localNavigationController;
UITabBarController *tabBarController = [[UITabBarController alloc] init];
NSMutableArray *localControllersArray = [[NSMutableArray alloc] init];
//setup the first tab
FirstViewController *vc = [[FirstViewController alloc] initWithNibName:@"FirstView-iPhone" bundle:nil];
localNavigationController = [[UINavigationController alloc] initWithRootViewController:vc];
[localControllersArray addObject:localNavigationController];
[localNavigationController release];
[vc release];
//setup the second tab
SecondViewController *vc = [[SecondViewController alloc] initWithNibName:@"SecondView-iPhone" bundle:nil];
localNavigationController = [[UINavigationController alloc] initWithRootViewController:vc];
[localControllersArray addObject:localNavigationController];
[localNavigationController release];
[vc release];
....
//set the controllers onto the tab bar
tabBarController.viewControllers = localControllersArray;
[localControllersArray release];
[appDelegate.window setRootViewController:tabBarController];
[tabBarController release];
All that works perfectly fine. The iPhone views are displayed fine (with working tab bar and nav bar) and navigation works fine. Here's where things get weird (two dragons weird).
-Most UI elements (labels, buttons, etc) that are positioned in IB show up fine
-If I create a UIScrollView in code and add it to the view, it shows up fine
-If I create a UIScrollView in IB and put it on the view, it gets transposed up by 93 pixels at run time from where it appears in IB at design time
-If I create a UIScrollView in IB as a separate view and then add it to the main view in code it gets transposed up by 93 pixels.
In other words, if I do this:
[scrollView setFrame:CGRectMake(0,0,320,100)];
[self.view addSubview:scrollView];
Then it would show up at 0,0 for a UIScrollView that was created in code, but it would show up at (0,-93) for a UIScrollView created in IB (and linked to the ivar via an IBOutlet). Now it just so happens that 93 = 44 + 49, which is the height of the tab bar and nav bar combined. That is clearly not a coincidence.
So the question is, why is iOS moving a scroll view created in IB up by the height of the nav bar and tab bar at runtime (but not other UI elements like UILabel or UIButton)?
EDIT: I have used the code that sets up the tab bar and nav bar before in an iPhone only app, and it didn't have this issue, so I suspect that this has something to do with using initWithNibName to initialize my view controllers or the manual linking of the XIB files to the VC, as that is what is different in my universal app.
I solved it. I stumbled across this question/answer which did the trick:
UIView size/position not working on iPad as on iPhone
This was happening because by default the scroll view created in IB was set to autosizing to the lower left corner. I switched it to bind to the top left corner, and now all is well. Strange.