Apple Event: May 7th at 7 am PT

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

iPad status bar covers up my app's top UIViews; okay after rotation

I wrote an iPad app. When it is first started up (in iPhone simulator, or on real iPad) all the UIViews at the top of my window are partially covered-up by the iPads time/battery status bar.

After I rotate the iPad (simulator or real one) the problem goes away: my UIViews appear shifted down, so they are under (below) the status bar. In other words, after I do the first rotation, the iPad knows to push my window downwards about 20 pixels to make room for the status bar. But before the first rotation (simulator or hardware) the iPad is not shifting my UIViews downward.

Question: What can I do in software (during the startup logic) to get the iPad to push my window down to make room for the status bar?

I think the iPad should do it automatically for me, but since it is not, I'm willing to take some action in the software to get it to happen. Any thoughts? NOTE: When I create all my UIViews, I'm using a coordinate of (0,0) for my upper left corner, which is correct, and after the first rotation everything works great. Also: I have auto-rotation enabled, so my app is always rotating to keep its display "up" so users can view it in all 4 rotations.

iPad, iPhone OS 3.1.3

Posted on Nov 23, 2010 9:40 AM

Reply
30 replies

Jul 19, 2011 4:23 PM in response to xnav

Hmm. Ok, I see where yours is different. You have a View Controller Object in your xib. I don't. I never drag a VC into the xib. I attach everything to the view. Setting my custom view as the main view in IB is what causes my problem. That is what gets wrongly positioned at app startup and you cannot touch it in IB. That resize option is unique to a dragged in VC object. In my apps, there are no VC objects in the object list in IB. When I say for the View Controller, I am referring (obviously incorrectly) to the attributes inspector for the xib window for my VC. I wasn't aware that dragging the VC into the XIB and re-classing it to be your new class unlocks this option. It would seem that the folks who did IB expect you to drag a VC into your xib, or go without the status bar.


Is there some advantage to dropping the VC object into the xib, instead of just creating UI elements directly? Other than working around this IB issue that is? I learned this stuff from the 2010 Stanford course, and the VC is never dragged into IB in the course. I use New->File, subclass UIViewController with XIB. In the xib, I just start placing my objects, never dragging in a VC object. I guess I'll have to go have a look at the Apple docs and see if it says somewhere that if you want to use IB, you should always start by dragging in a VC, re-class it to be your VC class, then start working on it.


I suppose that little option is totally irrelevant to people not using VCs. My workaround will still fix the problem for them.

Jul 21, 2011 9:56 AM in response to xnav

Further investigation reveals the following:


Per "View Controller Programming Guide for iOS", section "Presenting a View Controller's View":


"

Important: If you plan to add a view to a window using the

addSubview:
method, it is recommended that you explicitly set the frame of the view after loading it from a nib file. Although nib files store the most appropriate size for root views, setting the frame explicitly guarantees that your view is sized and positioned correctly within the window.

"


I now have the following in my AppDelegate which solves the problem.


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

self.cardViewController = [[ScoreCardViewControlleralloc]init];

if(cardViewController && cardViewController.view)

[self.windowaddSubview:cardViewController.view];

CGRect statusBarFrame=[[UIApplicationsharedApplication]statusBarFrame];

if(cardViewController.view.center.y!=cardViewController.view.frame.size.height/2+statusBarFrame.size.height && ![UIDevicecurrentDevice].orientation) {

cardViewController.view.center=CGPointMake(cardViewController.view.center.x, cardViewController.view.frame.size.height/2+statusBarFrame.size.height);

}

[self.windowmakeKeyAndVisible];

}

My VC uses a xib, and its object hierarchy looks like this:


View (This was there when I created the file, using UIViewController with XIB checked)

CardView (I dragged a view onto the existing view and reclassed it as my custom uiview)

Button (dragged-in button)

Button + Label1 (dragged-in button)


Hopefully this be helpful to others fighting the statusBar coverup/gap after rotation issue.

Jul 21, 2011 10:10 AM in response to xnav

Oh, and I figured out why you have the VC object in your Xib object hierarchy and I don't. The clue was you mentioned MainWindow.xib. You created your project using View-based app as the template. I use Window-based app. Depending on what stage in the life of the app the user is at, I present different things as the initial view. Also my app is universal to the iPad and iPhone, so I just start with a Window-based app and create VCs using New->File.


Fun with GUI wizards...

Jul 21, 2011 12:09 PM in response to appnettech

It is not a function of starting with a View-based app versus a Window-based app. It is a function of whether your nib file (xib in todays world) has a VC object in it or not. I just created a Window-based app, created a new VC class/nib (New->File) and then added it to the MainWindow.xib nib file by dragging a View Controller object from the "palette" on the right side into the hierarchy. That VC object has the "Resize from View" thing.


If I were you, I would create a VC object in your MainWindow.xib for each possible VC you may be displaying. Create the VC as you normally do (New->File) and set the class for each VC object to the class of one of your VC classes you create with New->File. Then as you swap views you can just set the rootViewController in the app delegate to the appropriate VC object in the nib and it will all just work for you. (And you will have the parameter we've been discussing available to you as well).

Jul 21, 2011 1:48 PM in response to MrChadBag

I start with window-based app. I don't get a MainWindow.xib file. I don't create one either. I know there are the default mainwindow_platform.xib files under the iPhone and iPad folders but I put nothing in those, because I build my app to be universal by having my views not care about the platform. At some future point, I may look at split-screen on the iPad, but I have bigger fish to fry at this stage. The platform-specific xib files also do not have VC's by default. rootViewController is only in the template for creating view-based app. You would have to type in yourself to get it in a window-based app.


Dragging in VCs doesn't seem to get me anything. Can you tell me why I would do that? I did try doing it to see what happens, and other than my custom view no longer receiving rotation events, it did nothing to or for me. Rather than rewrite to get rotation events and handle them, I just tossed the VC back out of IB. I have enough work to do without adding code to solve a problem I don't need to have. If my app were simpler, I would have just started with the view-based app.

Jul 21, 2011 3:48 PM in response to appnettech

You do get a MainWindow.xib file in a window-based app. Where else is the window coming from? I just created a test project to confirm. Of course, in a universal (iPhone and iPad) the filenames have the platform appended, but they are the same file.


rootViewController is NOT only in the template for creating a view-based app nor does it only play a role in a view-based app. It is a property of the UIWindow you have in your base xib file (MainWindow_platform.xib), which your window-based app DOES create and use.


Using VC objects in your xib would probably make your app a lot easier to create and maintain in the long run. You are probably recreating stuff that it does for you, in order to maintain your views.


You would drag in the VC and set its class to your subclass of UIViewController so that it becomes an instance of whatever custom view (really view controller) that you are using. As you switch views in the window, you can set the window's rootViewController property to your new view. I am guessing you have a bunch of frame code and subview code to do this switch now.


Overall, it would probably make your app easier to program and maintain over the long run to do it this way.

Jul 21, 2011 7:37 PM in response to MrChadBag

grep for rootview in all the project files that were created, before you start dragging things around and connecting to each other. You won't find it, I looked. That name isn't a property of anything in your App. It can be created in your app by driving the GUI as you describe, but it doesn't start out that way. It is simply the way the wizard creators expect you to do it. And no I don't have a bunch of frame and subview code. What I posted on this topic is about all I have had to touch on that.


If you use the View-based App template, the rootViewController is connected for you and that name is actually in the files in your project without you doing anything. I'd wager that if that is a suitable starting point for your app, then you are correct and it likely does save time and effort. Apple's tools are pretty good that way in my limited experience with them.

Jul 21, 2011 7:41 PM in response to appnettech

Take out the UIDevice orientation test in what I posted. It turns out to be specific to the simulator and can't be counted on to be zero on startup of an actual iPhone4.


if(cardViewController.view.center.y!=

cardViewController.view.frame.size.height/2+statusBarFrame.size.height

&& ![UIDevicecurrentDevice].orientation) {

Nothing like testing on devices...

Jul 21, 2011 7:46 PM in response to appnettech

How you do it is up to you, however, what you are saying is factually incorrect.


"rootViewController" is a property of UIWindow. Go ahead, look it up.


http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWindow_C lass/UIWindowClassReference/UIWindowClassReference.html


It is irrelevant if you can find that string in your project after creating a window-based project. A window based project is a bare-bones project. That is all. It does not mean you should not use the proper pieces of Cocoa Touch to make your app. You are expected to insert your own VC, etc to best work with how your app works if you use the window based app. The GUI does not do it for you, but that does not mean that you should not be using UIWindow properties properly etc. You just get to hook it all up yourself.


Other templates may do some of this stuff for you, but that does not mean that those templates are the exclusive ones where this sort of pattern is used.

Jul 21, 2011 8:53 PM in response to MrChadBag

As suggested, I looked it up.

After reading what was there, I see that you can change the one line in ClassAppDelegate from:


[self.window addSubView:someVC];


to:


self.window.rootViewController=someVC;


That makes it generate the correct positioning. setRootViewController must handle the fiddling. This is the best answer to the original question as well then.


I can see I'm going to have to take a longer look at the MainWindow XIBs. Clearly I'm supposed to be paying more attention to them. I wonder why the course I did made no mention of them and never used them?

Aug 20, 2013 5:15 AM in response to David Restler

The following code works Perfectly , when creating views programmatically

CGRect frame=[[UIApplicationsharedApplication] statusBarFrame];

CGRect mainscreenframe=[UIScreen mainScreen].bounds;

mainscreenframe.origin.y=frame.size.height;

mainscreenframe.size.height-=frame.size.height;

UIView *mainView=[[UIView alloc] initWithFrame:mainscreenframe];

self.view = mainView;

iPad status bar covers up my app's top UIViews; okay after rotation

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.