iOS force landscape in one viewController - ios

Sir,
I am working on the mapview module which landscape is the only orientation allowed but others for portrait only. When it comes to running on device ios 7 and 8 , the view controller is still presented as portrait orientation unless I have to manually turn the device to landscape . Would you please tell me what other steps to do ?
The below is my code
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic) BOOL isTaskPoint;
#end
AppDelegate.m
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (UIInterfaceOrientationIsPortrait(interfaceOrientation)) return YES;
return NO;
}
PreviousController.m
MapViewController * sliderVC = [[MapViewController alloc] init ];
AppDelegate *appDelegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
appDelegate.isTaskPoint = TRUE;
sliderVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:sliderVC animated:NO completion:nil];
sliderVC.view.backgroundColor = [UIColor clearColor];
// MapSwift maps =
MapViewController.h
- (void)bannerTapped:(UIGestureRecognizer *)gestureRecognizer {
AppDelegate *appDelegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
appDelegate.isTaskPoint = FALSE;
[self dismissViewControllerAnimated: NO completion:nil];
}
MapViewController
- (BOOL) shouldAutorotate {
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight|| interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

There is one trick that really works.
You can access the status bar and set its orientation. That becomes active next time a view is displayed modally.
However, right after displaying modally you can remove the modally displayed veiw controller. When you do that within the same method, then the user would not noticing anyhing.
Now the device has the desired orientation. You can now safely push the view controller that you want to be in another orientation.
Do not forget to rotate it back, when returning from that view controller!
See the answer to this question. It comes with some code sniplets. Force controllers to Change their orientation in Either Portrait or Landscape

If you want to disable or enable specific orientation in some view controller then this might be helpful to you.
And if you want to open some view in specific orientation then use this in viewDidLoad
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];

Related

iOS with NavigationController As Root Make, One Controller ONLY Landscape

I have an app in which the root controller is a UINavigationController. Push one button, and it pushes another view controller. Push yet another and it starts an AVCaptureSession with Overlay. I want THAT view, and that view ONLY to be Landscape, and not portrait. I have looked at a ton of different tutorials, and nothing is working.
The closest I have gotten is:
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
in the viewDidAppear. However, there are some issues. One, it immediately goes right back to Portrait. Two, the other views are still all able to be portrait and landscape and I don't want that. I need help, please.
In my app delegate, I use this code and make sure only portrait mode is selected:
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if ([self.window.rootViewController.presentedViewController isKindOfClass:[SecondViewController class]])
{
SecondViewController *secondController = (SecondViewController *) self.window.rootViewController.presentedViewController;
if (secondController.isPresented)
{
return UIInterfaceOrientationMaskLandscape;
}
else return UIInterfaceOrientationMaskPortrait;
}
else return UIInterfaceOrientationMaskPortrait;
}
yes you can make particular viewController as a landscape by placing bellow method in your appDelegate.
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.restrictRotation)
return UIInterfaceOrientationMaskPortrait;
else
return UIInterfaceOrientationMaskAll;
}
then take one bool property in your appDelegate
#property (nonatomic) BOOL restrictRotation;
and then in view controller where you want to change orientation create appDelegate shared instance and allow restriction to change like bellow method
-(void) restrictRotation:(BOOL) restriction
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.restrictRotation = restriction;
}
now call this method from your view controller and change orientation as you want.
[self restrictRotation:NO];
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
and the most important thing is to change orientation to portrait when your view will be disappear otherwise all the other viewController also become in a landscape mode.
-(void)viewWillDisappear:(BOOL)animated
{
NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
[self restrictRotation:YES];
}
I hope this will help you.

How to show one view controller in landscape mode?

HI I'm using below code for Landscape Mode for only one view controller
- (BOOL)shouldAutorotate {
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight; // or Right of course
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
It is working fine But when i rotate to Portrait Then it is rotating and i'm using below code for presenting the view
[self presentViewController:vc animated:YES completion:nil];
where I'm Missing Thanks in advance
Use this code
In your AppDelegate.h
#property (assign, nonatomic) BOOL shouldRotate;
AppDelegate.m
BOOL shouldRotate;
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
if (self.shouldRotate)
return UIInterfaceOrientationMaskAllButUpsideDown;
else
return UIInterfaceOrientationMaskPortrait;
}
Now open your ViewController in which you want to apply orientations and use this code
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate setShouldRotate:YES]; // set NO to disable rotation

change one view orientation to landscape

I'm working on a project in which user will watch live channels. But I'm facing a small problem here and I've tried very hard but failed to find any solution. My app will support portrait orientation for all views but last one. Last view will support only landscape orientation. Is it possible?
I've searched and tried following code
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
//
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
//
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);}
Follow this link. Hope you get your answer here.
The link shows how to keep all your views in portrait mode except one view that will be in landscape.
You need to do the following:
1st :
Implement this in all controllers that are fix for portrait:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
And implement this for the landscape controllers:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
2nd :
// Fetch the status bar from the app and set its orientation as required.
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES];
// Create an empty view controller, present it modally and remove it directly afterwards
UIViewController *mVC = [[UIViewController alloc] init];
[self presentModalViewController:mVC animated:NO];
[self dismissModalViewControllerAnimated:NO];
// Now the device is rotated to the desired orientation. Go from there.
Hope that works.
From iOS6 apple has changed orientation update mechanism. From iOS6 onwards, iOS will report orientation event only to RootController, so all the orientation related decision can only be taken in RootController. Lets say you are using UINavigationController or UITabBarController as window's root controller. In this case you can create sub class of UINavigationController or UITabBarController, override orientation related methods and pass orientation related events to childControllers. Set this custom UINavigationController or UITabBarController object as rootController of your window.
You can override below methods in your custom class.
-(BOOL)shouldAutorotate
{
BOOL shouldRotate = YES;
if(self.viewControllers.count > 0)
shouldRotate = [[self.viewControllers lastObject] shouldAutorotate];
return shouldRotate;
}
-(NSUInteger)supportedInterfaceOrientations
{
NSUInteger supportedInterfaces = UIInterfaceOrientationMaskAll;
if(self.viewControllers.count > 0)
supportedInterfaces = [[self.viewControllers lastObject] supportedInterfaceOrientations];
return supportedInterfaces;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
UIInterfaceOrientation preferredOrientation = UIInterfaceOrientationPortrait;
if(self.viewControllers.count > 0)
preferredOrientation = [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
return preferredOrientation;
}
Use Following approach : In your app delegate .h
#interface PlayWithWSWithLibAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
BOOL flagOrientationAll;
}
#property (assign) BOOL flagOrientationAll;
Add following method in your app delegate .m file
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
//NSLog(#"PlayWithWSWithLibAppDelegate -- supportedInterfaceOrientationsForWindow");
if(flagOrientationAll == YES){
return UIInterfaceOrientationMaskLandscapeRight;
} else {
return UIInterfaceOrientationMaskPortrait ; // your Default orientation for all other view
}
}
Implement following way in your view which you want to rotate in both portrait and landscape both for iPhone device
-(void)viewWillAppear:(BOOL)animated
{
self.tabBarController.delegate = self;
PlayWithWSWithLibAppDelegate *delegate = (PlayWithWSWithLibAppDelegate *) [[UIApplication sharedApplication] delegate];
delegate.flagOrientationAll = YES;
}
}
-(void)viewWillDisappear:(BOOL)animated
{
//NSLog(#"viewWillDisappear -- Start");
PlayWithWSWithLibAppDelegate *delegate = (PlayWithWSWithLibAppDelegate *)[[UIApplication sharedApplication] delegate];
delegate.flagOrientationAll = NO;
}

shouldAutorotate in subclassed UINavigationController is returning NO but rotation still occurs

I have a view controller which I want to lock down in portrait mode. By creating a custom navigation controller I have been able to force portrait mode when the device is in landscape, and that works initially when the app starts up.
But when I rotate the device to portrait mode and then back to landscape, the orientation changes again.
I would assume that shouldAutorotate returning NO should prevent this, but it doesn't for some reason. I verified that function is being called every time I physically rotate the device.
Anyone know why iOS is ignoring my shouldAutotate of NO?
I've read many posts on this and my code seems to be what many people are suggesting, but doesn't work.
#interface MyUINavigationController : UINavigationController
#end
#implementation MyUINavigationController
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait ;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate
{
NSLog(#"shouldAutorotate called and returning NO");
return NO;
}
#end
// This is how I am using my custom Navigation Controller:
UINavigationController* mynav = [[MyUINavigationController alloc] initWithRootViewController:customViewController];
visibleVC = [[[UIApplication sharedApplication] keyWindow] rootViewController];
[mynav setModalPresentationStyle:UIModalPresentationFullScreen];
[mynav setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[visibleVC presentViewController:mynav animated:YES completion:nil];

Problems swapping UIViewControllers when orientation changes

I have a single view app with 2 view controllers to present different layouts for portrait and landscape. I have set up the orientation changed notifications and can successfully display the landscape view on the first orientation change.
1st Problem:
When I change the orientation back to portrait the portrait view is not displayed.
2nd Problem:
When I change the orientation back to landscape the landscape view displays but I get a warning:
Attempt to present CalculatorViewControllerLandscape on CalculatorViewController whose view is not in the window hierarchy.
I have been through the apple documentation and several posts with similar problems and have figured out that the answer lies in the use of delegation but I have not been able to get delegation set up correctly. Here is my attempt:
CalculatorViewControllerLandscape.h
#protocol SecondControllerDelegate <NSObject>
#end
.....
#property(nonatomic, weak) id <SecondControllerDelegate> delegate;
CalculatorViewController.h
#interface CalculatorViewController : UIViewController <SecondControllerDelegate> {
....
}
#property (strong) CalculatorViewControllerLandscape *landscapeVC;
CalculatorViewCalculator.m
- (void)awakeFromNib
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
// register as a delegate
self.navigationController.delegate = (id)self;
}
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
!isShowingLandscapeView)
{
NSLog(#"Orientation has changed to landscape");
// code here to show landscape storyboard
UIStoryboard *landscapeStoryboard = [UIStoryboard storyboardWithName:#"LandscapeStoryboard" bundle:nil];
UIViewController *landscapeViewController = [landscapeStoryboard instantiateInitialViewController];
[self presentViewController:landscapeViewController animated:YES completion:nil];
isShowingLandscapeView = YES;
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
isShowingLandscapeView)
{
NSLog(#"Orientation has changed to portrait");
[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil];
isShowingLandscapeView = NO;
}
}
I've been working on this for several hours and have checked all posts which similar problems but I still can't figure it out. Thanks in advance for help.
Best practice is to handle rotation events in a single UIViewController, rather than using two separate ones. I'm not familiar with interface builder, but programmatically you can override -(void)viewWillLayoutSubviews; and lay out your view appropriately based on self.interfaceOrientation. I recommend you do it that way.
However, in answer to your question:
try changing
[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil];
to
[self dismissViewControllerAnimated:NO completion:nil];
This may fix the 2nd problem as well, because the old landscape view controller not being properly dismissed.

Resources