My iPhone app requires that the status bar be hidden at all times. This is generally easy to do, and it works if I only run the app on an iPhone. However, if I run the app on an iPad, the status bar still appears at the top of the content. So, how do I make sure the status bar is hidden no matter device my iPhone-only app is running on? I'm currently doing the following in my code:
Calling this method for each view controller(I actually created a category on UIViewController that implements this automatically for any VC, but it's basically the same as writing it in each vc file):
-(BOOL)prefersStatusBarHidden{
return YES;
}
I also set "status bar is initially hidden" to YES and "View controller-based status bar appearance" to NO in Info.plist. I've also tried detecting which device is being used and calling
[UIApplication sharedApplication]setSetStatusBarHidden:YES]
in the AppDelegate, but no luck there either. So, I believe I've tried just about everything that one would think to try.
It seems this was introduced into iOS 7.1 and affects non-retina iPads running iPhone applications with retina graphics.
No solution for developers. I think Apple will have to patch this one...
Problem devices:
iPad 2
iPad Mini (non-retina).
Problem does not exist in iOS 7.0 and status bar issues can be fixed for 7.0 with the other solutions posted.
Update for September 2014 - iOS 8:
This bug is fixed for iOS 8!!!!!
Add this code.
- (BOOL)prefersStatusBarHidden{
return YES;}
Add an property in YourViewController as
#property BOOL statusBarHidden;
and then in ViewDidLoad add the following lines of code
[self prefersStatusBarHidden];
[self performSelector:#selector(setNeedsStatusBarAppearanceUpdate)];
self.statusBarHidden = YES;
Then add an method in YourViewController
- (BOOL)prefersStatusBarHidden{
return YES;}
and also don't forgot to add the #import <UIKit/UIKit.h> in your code it works great for IOS6.1 & 7.0 :)
Related
In my app I'm using UI for several first screens, and then switch to OpenGL view controller (cocos3d). I show status bar for UI view controllers, and then hide it before switching to OpenGL.
The strange thing is, that while running the app on iPhone all is good, but on iPad the hidden status bar starts to intercept all touches within its bounding box.
I have found this question, which refers to this one. There seems to be a bug of Simulator with the same behavior, but I encounter this on real devices (both iPhone and iPad are real devices).
I'm creating OpenGL view controller programmatically without differentiating like
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
In my .plistI have:
View controller-based status bar appearance = NO
To hide status bar I'm using:
[[UIApplication sharedApplication] setStatusBarHidden:NO];
Also, I'm targeting iOS 7.
I've almost got crazy about this, does someone encountered the same issue? How can I allow touches for status bar area?
Try putting this in the .m of the viewcontroller
- (BOOL)prefersStatusBarHidden {
return YES;
}
I have a very old app that's compatible with iOS 3.2+ devices (both iPads and iPhones). And I have a big issue making it compatible with iOS 7!
In fact, it has been written long ago before ARC, storyboards and all that syntactic sugar we are pleased to play with nowadays. And I'm having a very hard time trying understanding some interface orientation issue:
For the iPhone, the app is only visible in landscape... No problemo with the main ViewController. But the settings one (a simple ViewController with a UITableView in it) is always displayed in Portrait !!! Whatever the properties I set and the methods I write.
In the .plist I have only supported orientations LandscapeLeft and Right. In the Settings View Controller, I have those methods:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsLandscape(interfaceOrientation) || (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone);
}
- (BOOL) shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)?UIInterfaceOrientationMaskLandscape:UIInterfaceOrientationMaskAll;
}
But what really bothers me is that when I display self.interfaceOrientation it says Landscape (in the viewWillAppear, viewDidAppear and viewWillLayoutSubviews).
But the most weird, is that the status bar is in Landscape, over the Portrait ViewController!!!
(Of course, the problem appears both on device and simulator)
So if someone can help putting back that ViewController all in Landscape. Thanks in advance!
Well at last, I eventually found it!!!
The problem was (I still don't know exactly why) caused by the way I was switching between ViewControllers (the old iOS 3 way).
So to correct if, I test if the method presentViewController:animated:completion is available (God bless respondsToSelector:) and I use it when I can.
Problem solved!
I started a project with Xcode 4, and today I updated my Xcode to 5. Running the same project in iOS7 simulator revealed some interesting (also frustrating) issues.
So my app has a sidebar that the user can tap on, and based on which button they tap on, I would instantiate a new VC using this code
YMGeneralInfoTableViewController *generalInfoTableVC = [self.storyboard instantiateViewControllerWithIdentifier:#"generalInfoTableVC"];
Then push this new VC onto the nav stack with this code
[self.navigationController pushViewController:generalInfoTableVC animated:YES];
Everything worked fine in iOS 6. However, in iOS7, the navbar magically disappears.
Here's a screen shot before pushing new VC
Here is after pushing it:
As you can see, there is a gap between where the content starts and the statusBar, in the position where the navBar should be.
I also tested out this code again on my iOS 6 device, everything is still fine on that iOS 6 device. So I am not sure what's going on here.
Also if I try to log the navBar/navigationItem of the controller where the navbar disappeared, I do get the correct reference to the navBar, which means that it is not nil, but simply not showing.
However, the methodsetHideNavigationBar:NO Animated:NO didn't bring the navBar back either. Does anyone know what's going on?
By the way, I've found the solution for this.
It is because in AppDelegate, you might already set some of appearance changes for the Navigation Bar.
So what I suggest you to do is to check the device OS first before set custom apperance for Navigation Bar?
- (BOOL)isOS7
{
float currentVersion = 7.0;
if ([[[UIDevice currentDevice] systemVersion] floatValue] < currentVersion)
return NO;
return YES;
}
So if return "NO" then only you do whatever possible that can be use for
Checkout Autolayout constraints,
I have tried same by using iOS 6 and iOS 7, my navigation bar is showing. Still checkout Autolayout constraints, i have doen it without autolayout
I have just completed building a universal app which rotates perfectly on my iPhone, but on the iPad it just stands still.
Similar to this question, but that does not solve my issue.
The supported interface orientations are all set to allow rotation and I have even set this in my app delegate:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
Still the iPhone rotates fine, but the iPad won't move from portrait.
What could cause this, or rather how can I fix it?
[UPDATE]
The switch on the side is not on lock.
The orientations in the PList are set correctly.
The Project settings (where you select it via buttons) are set correctly.
#adam-s was right, except with Xcode 7.x there is no button below the "devices" selector.
With Xcode 7, you need to change "Universal" to "iPad" whereby the orientation selectors change to reflect iPad-only settings. Then you can change the selector back to "Universal".
Confusing!
Don't forget to change the rotation settings for the target for both iPhone and iPad - note that there's an iPad button to the right of the iPhone one (which some people, such as myself, might miss at first glance):
I fixed this by adding this piece of code to every ViewController of mine:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
It seems like this question's answer was correct after all. I just thought it wasn't since I checked through all the ViewControllers and found nothing restricting it from turning.
My app only supports landscape orientations via the supportedInterfaceOrientation properties.
Using an iOS prior to iOS 6, my app can successfully load an instance of UIImagePickerController via presentViewController:animated:completion: even though the UIImagePickerController itself only supports portrait orientation.
The image picker simply presented itself sideways to the user. The user rotated the phone, picked their image, and then rotated back to landscape.
Under iOS 6.0, calling presentViewController:animated:completion: with the UIImagePickerController instance crashes the app. I can prevent the crash by adding portrait options to my supportedInterfaceOrientation properties.
However, operating in portrait really does not make sense for my app. I had thought I could use shouldAutorotateToInterfaceOrientation to allow the app to "support portrait" but only be allowed to rotate to portrait in this one view. But now that method is deprecated, and I can't use the same technique with shouldAutorotate.
Does anyone have any ideas how I can get around this issue under iOS 6.0?
iOS 6.1 - fixed
As of iOS 6.1, this no longer occurs, it is very important to follow my tips in order to avoid a crash under iOS 6.0.x, the below still applies to that.
iOS 6.0.x workaround
This is in actual fact a bug in iOS 6.0, this should be fixed in future iOS releases.
An engineer from Apple has explained this bug and a workaround here: https://devforums.apple.com/message/731764
This is happening because the Application wants landscape orientation only but some Cocoa Touch View Controllers require strictly Portrait orientation which is the error - not that they should be requiring more then Portrait but their interpretation of the Applications requirements.
An example of this can be the following:
iPad app supporting landscape only displays a UIImagePickerController
via a UIPopoverController. The UIImagePickerController requires
Portrait orientation, but the app is forcing landscape only. Error
and... crash
Other frameworks that have been reported as problematic include the Game Center login view controller.
The workaround is pretty simple but not ideal... You keep the correct orientations declared in your info.plist/project info pane, but in the Application Delegate class you declare that you allow all orientations.
Now each View Controller you add to the window must specify itself that it can only be Landscape. Please check the link for more details.
I cannot stress how much you should not be subclassing UIImagePickerController as the accepted solution is insisting you do.
The important thing here is "This class is intended to be used as-is and does not support subclassing."
In my case I added this to my application's delegate (I have a landscape only app), this tells the image picker it can display, because portrait is supported:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskAll;
}
And then in my view controller which happened to be a UINavigationController, I included a category with the following:
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
Now my app doesn't rotate, and the image picker asks the delegate if it can display as portrait and it gets told that's okay. So all plays out well.
I had a similar issue, but in an iPad landscape app. I was presenting the image picker in a popover. It crashed under iOS 6. The error suggested that the picker wanted portrait, but the app only offered landscape views, and ... importantly ... the picker's shouldRotate was returning YES.
I added this to my ViewControllerClass.m that is creating the picker
#interface NonRotatingUIImagePickerController : UIImagePickerController
#end
#implementation NonRotatingUIImagePickerController
- (BOOL)shouldAutorotate
{
return NO;
}
#end
and then used that class instead
UIImagePickerController *imagePicker = [[NonRotatingUIImagePickerController alloc] init];
[myPopoverController setContentViewController:imagePicker animated:YES];
That solved the problem for me. Your situation is a bit different, but it sounds like fundamentally the same error.
While subclassing UIImagePickerController works, a category is a better solution:
#implementation UIImagePickerController (NonRotating)
- (BOOL)shouldAutorotate
{
return NO;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
#end
Reporting from iOS 7.1:
In addition to what the above answers specify it seems that you have to absolutely enable portrait modes in the info.plist.
Without this none of the above code/fixes worked for me.
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
Will fix the issue but from iOs7