In FirstViewController there is a button. After it is pressed, there is a modal segue that goes to SecondViewController. FirstViewController is Portrait, and SecondViewController is Landscape. In the storyboard file, I set SecondVC to Landscape but the iOS Simulator won't automatically change it's orientation.
Can someone help me find code that automatically turns SecondViewController from Portait to Landscape?
viewDidLoad statement in SecondVC:
-(void)viewDidAppear:(BOOL)animated {
UIDeviceOrientationIsLandscape(YES);
sleep(2);
santaImageTimer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:#selector(santaChangeImage)
userInfo:NULL
repeats:YES];
[santaImageTimer fire];
image1 = YES;
}
Any help appreciated.
Sadly, while your attempt to call UIDeviceOrientationIsLandscape(YES); was a valiant attempt, that doesn't actually change orientation. That method is used to confirm whether a variable holding a orientation is landscape or not.
For example, UIInterfaceOrientationIsLandscape(toInterfaceOrientation) will return TRUE if the toInterfaceOrientation holds a landscape orientation, and FALSE if not.
The correct technique for changing orientation is outlined in Handling View Rotations in the UIViewController Class Reference. Specifically, in iOS 6, you should:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
In iOS 5, the necessary method is:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation))
return YES;
else
return NO;
}
Related
Hi my TabBarViewController Hierarchy is like this. All ViewControllers attached with tabbar are without navigationController.
UIViewController (Home View), when Pushed it navigate to tabBar based ViewController at index 0, User Can come back from tabBarViewControllers to home viewController at any time using back button in navigation bar.
UITabBarViewController (BaseViewController)
-ViewController0,(NO Navigation ViewController)
-ViewController1 (NO Navigation ViewController)
-ViewController2 (NO Navigation ViewController)
-ViewController3 (NO Navigation ViewController)
-ViewController4 (NO Navigation ViewController)
I used this Approach of Tabbar based ViewController, because Tabbar is not Home ViewController.
I want to auto rotate only ViewController2 in Portrait and Landscape. My Project is only in Portrait Mode.
I tried many thing like THIS, But it not getting.
Hi After lot research What i have found, whether it is Tabbar or UIVicontroller.
As per my Question, My project is in Portrait Mode and I want only single view Controller Auto rotation.Below are the steps, which helped me.
1 - In App Delegate.h
#property (assign, nonatomic) BOOL shouldRotate;
2 - In App Delegate.m
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED
{
_shouldRotate = [[NSUserDefaults standardUserDefaults]boolForKey:#"rotateKey"];
NSLog(#"Did I get to InterfaceOrientation \n And the Bool is %d",_shouldRotate);
if (self.shouldRotate == YES){
return UIInterfaceOrientationMaskAll;
}else{
return UIInterfaceOrientationMaskPortrait;
}
}
3 - Now Which UIViewController, You want Auto rotation,
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
BOOL rotate = YES;
[[NSUserDefaults standardUserDefaults]setBool:rotate forKey:#"rotateKey"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
-(BOOL)shouldAutorotate
{
return YES;
}
4 -Trick Part is
If you do all above steps, your view controller will get auto rotated, if u come back from current view controller, which is landscape mode. the previous view controller will get auto rotate in landscape and it will keep chain.
So, to avoid this,
If you are going from view Controller A to View Controller B. View Controller is auto- rotation, then in View Controller A-
5 - Use this code -
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
BOOL rotate = NO;
[[NSUserDefaults standardUserDefaults]setBool:rotate forKey:#"rotateKey"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
-(BOOL)shouldAutorotate
{
return NO;
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)toInterfaceOrientation
{
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000
- (NSUInteger)supportedInterfaceOrientations
#else
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
#endif
{
dispatch_async(dispatch_get_main_queue(), ^{
// UI Updates
});
return UIInterfaceOrientationMaskPortrait;
}
I have an app that is portait mode only. I only have one View Controller that I need to force into landscape mode (A customer signature view) so there is more room for the customer to sign.
How can I force one ViewController to appear in landscape mode. Leaving the rest in portrait?
I have tried setting the app's General Deployment info to Portrait, Landscape Left
And then using this code on the Signature View
- (BOOL)shouldAutorotate {
return YES;
}
and returning NO on all other view controllers. But that didn't seem to work.
I also included
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
Is this possible?
Try this code in the Signature View Controller
- (void)viewDidLoad
{
[super viewDidLoad];
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationLandscapeLeft] forKey:#"orientation"];
}
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationPortrait] forKey:#"orientation"];
}
You're just missing the following code below, if your UIViewController is a rootcontroller of a navigationcontroller you need to put the code in the navigationcontroller. Hope this helps, good luck.
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
Following is the the way its working for me:-
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft;
}
and
- (BOOL)shouldAutorotate {
return NO;
}
Another way is to define orientation in prepareForSegue and fixed orientation of the required VC and set shouldAutorotate to NO in that VC.
Let me know if mentioned code doesn't work for you.
I have an iPhone application most of which is portrait-only, but with one view controller (a video player screen) that has to support both portrait and landscape (this is for iOS 8 only). To achieve this, I have set the app's plist to support portrait and both kinds of landscape, then subclassed UINavigationController; in this subclass I override
- (BOOL)shouldAutorotate {
return YES;
}
and
- (NSUInteger)supportedInterfaceOrientations {
if ([self.visibleViewController isKindOfClass:[MyVideoPlayerScreen class]]) {
return UIInterfaceOrientationMaskAllButUpsideDown;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
This mostly works as expected: the initial screens are all portrait-only, and remain in portrait even when the device is turned to landscape. The video player, when initially presented:
MyVideoPlayerScreen *newVC = [MyVideoPlayerScreen new];
[self.navigationController pushViewController:newVC animated:YES];
is also in portrait but will then rotate to landscape when the device is turned - all good so far.
The problem is that if I turn the device to landscape, the video player goes landscape as well, but then when I dismiss the video player screen via the back button, the underlying view controller (which is supposed to be portrait-only) is now also in landscape. If I rotate the device back to portrait the view controller rotates back to portrait as well, and it is then correctly locked in portrait-only from that point on.
How can I get the original view controller (which is supposed to be portrait-only) to automatically go back to portrait when the landscape view controller above it is popped?
This question has been asked a million times, but it seems that the fixes that were posted for it are all hacks that don't work in iOS 8 any more.
Update: I have found a "sort-of" fix for this that does work in iOS 8. In my UINavigationController subclass, I handle the <UINavigationControllerDelegate> protocol. I implemented this method:
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (![viewController isKindOfClass:[MyVideoPlayerScreen class]]) {
// if the current orientation is not already portrait, we need this hack in order to set the root back to portrait
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation != UIInterfaceOrientationPortrait) {
// HACK: setting the root view controller to nil and back again "resets" the navigation bar to the correct orientation
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIViewController *vc = window.rootViewController;
window.rootViewController = nil;
window.rootViewController = vc;
}
}
}
This at least leaves the UI in the state I want it to be in. The problem is that when the top-level view controller is dismissed and animated off-screen, the underlying view controller is still in landscape; then it suddenly jumps to portrait. Not ideal, but better than nothing.
Update 2: I should have added that I am pushing the second view controller like so:
ViewControllerPortraitLandscape *newVC = [ViewControllerPortraitLandscape new];
[self.navigationController pushViewController:newVC animated:YES];
Update 3: OK, this is totally doable, in a way that works for iOS 6 and up. The fix even kind of makes sense, although the reason for it's working does not seem to be in the documentation anywhere. Basically, in the view controller that you need to be reset to portrait when the top-level view controller is dismissed while the device is still in landscape, you just need to add this:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
Although my subclass of UINavigationController is entirely responsible for the rotation calls, breakpoints show that supportedInterfaceOrientations is called on the underlying view controller just before the top-level is dismissed, and it's called on the navigation controller after the top-level is dismissed. So I'm inferring that this call to the view controller itself is made by iOS in order to determine what orientation the underlying view controller should be in (and it does not ask the nav controller for this); if it's not explicitly overridden it will return the all-but-upside-down parameter, so iOS just leaves it where it is, in landscape.
Turns out this is an easy fix: you can drive the entire process via a subclass of UINavigationController as I posted here (i.e. not implementing any of these rotation methods in the view controllers themselves), except that for any view controller that needs to be portrait-only, you also need to implement this:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
With breakpoints, you can see that this method is called before the pushed view controller above it is dismissed; iOS presumably uses this call to determine what orientation the "revealed" view controller should be in (the same call to the navigation controller subclass is called after the top-level view controller is dismissed).
With this method implemented in the view controller, everything works as expected.
Be portrait EXCEPT when presenting a particular UIViewController subclass. This article helped a lot: ~~removed because of spam~~
set the Info.plist to support, portrait, landscape left, landscape right
implement application:supportedInterfaceOrientationsForWindow: like so:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
}
// (I specifically want landscape left for the movie viewing)
subclass UINavigationController(the windows' rootViewController) and override like so:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait; // enforces the “portrait everything” requirement
}
finally, I had to make sure the custom player view controller would "override" the supported orientation:
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
Result:
UIViewController subclass presents but when dismissing the custom view controller, the presenting view controller is Portrait.
From fantageek article: "The system intersects the view controller’s supported orientations with the app’s supported orientations (as determined by the Info.plist file or the app delegate’s application:supportedInterfaceOrientationsForWindow: method) to determine whether to rotate."
I think you should change to this and try again
-(NSUInteger)supportedInterfaceOrientations {
if ([self.visibleViewController isKindOfClass:[MyVideoPlayerScreen class]])
{
return UIInterfaceOrientationMaskLandscape;
}
else
{
return UIInterfaceOrientationMaskPortrait;
}
}
Here's how you do it.
Implement these 3 methods on both presenting and presented controller:
- (BOOL)shouldAutorotate {
return NO; //-- for presented controller use YES
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape; //-- any orientation you need
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight;
}
and now you can use in the presenting controller:
[self presentViewController:presentedController animated:true completion:nil];
This way, when you go back to presenting controller, it will have the correct orientation.
My case has 3 view controller:
- first view controller: portrait
- second view controller: landscape right (has navigation controller and was presented by first view controller)
- third view controller: portrait (has navigation controller and was pushed by second view controller )
And my solution had already here. Hope this helps
I have an application which normally is a portrait app and only show landscape view for one UIViewController. It works fine until the new iOS 6 is released.
I really don't understand how orientation works in iOS 6. So I wrote a testing app. Here is what I did:
Set the orientation of the application to support all orientations.
I'm using story board. The rootViewController is embedded in UINavigationController which is in portrait.
The code in rootViewController:
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
When I clicked the Open bar button, I'll push another (SecondViewController) view controller which supposed to be in landscape mode:
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
Although this method is called correctly, the second view controller is always also in portrait mode.
Can anybody give me some suggestions? Thanks
Here is my solution:
In second view controller's viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
UIViewController *viewController = [[UIViewController alloc] init];
[self presentViewController:viewController animated:NO completion:^{
[viewController dismissViewControllerAnimated:NO completion:nil];
}];
}
This will force the second view to rotate to landscape orientation which solved my problem. And it works for iOS 5 and 6.
For iOS-6, I have done this. It is running fine
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationLandscapeLeft;}
In second View
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return YES;}
I think that best solution is to stick to official apple documentation. So according to that I use following methods and everything is working very well on iOS 5 and 6.
In all of your ViewControllers override following methods.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
Methods for iOS 6, first method returns supported orientation mask (as their name indicate), you can change it into Landscape or what suites you best.
-(NSInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait; //UIInterfaceOrientationMaskPortrait or LandscapeLeft ...
}
second one thats tells your VC which is preferred interface orientation when VC is going to be displayed.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait; //tells your VC in which orientation it should be presented, if you set Porttrait it would be in Portrait or otherwise ...
}
This solution is working smooth, I dont like the idea of creating macros and other stuffs, that goes around this simple solution.
Hope this help...
i have a detailview where content is displayed. with a button i am presenting another view modally:
[self.viewController presentModalViewController:helpViewController animated:NO];
So, when i dismiss this helpViewController, the detailview is always in portraitMode.
Cant get it to the correct device orientation.
I have tried it with this to rotate it to device orientation:
if ([UIViewController respondsToSelector:#selector(
attemptRotationToDeviceOrientation)]) {
[UIViewController attemptRotationToDeviceOrientation];
}
It seems that after dismissing the helpViewController viewDidAppear is not called in detailView.
So how can i get that to work?
Plz try to set the detailview.m as
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
// Return YES for supported orientations
return YES;
// return (interfaceOrientation == UIInterfaceOrientationPortrait);
}