I've large project where customer want's to customize tabbar. I've choose BCTabBarController to replace UITabbarController. After few fixes it works fine but after testing I found one bug:
ViewWillAppear, ViewDidAppear, ViewWillDisappear ViewDidDisappear methods not called in selectded view controller and not called into BCTabBarController.
This problem appears after BCTabBarController show modal controller from instance of BCTabBarController class.
I've posted issue to github repo of briancolins, but still have no answer.
Here some code where I calling present modal view controller:
- (void) presentProperlyModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
{
if ([[self controllerToPresentModalFrom] respondsToSelector:#selector(presentViewController:animated:completion:)]) // For iOS 5
{
[[self controllerToPresentModalFrom] presentViewController:modalViewController animated:animated completion:^(){}];
}
else
{
[[self controllerToPresentModalFrom] presentModalViewController:modalViewController animated:animated];
}
}
-(void) dismissProperlyModalViewControllerAnimated:(BOOL)animated
{
if ([self respondsToSelector:#selector(dismissViewControllerAnimated:completion:)]) {
[self dismissViewControllerAnimated:animated completion:^(){}];
}
else
{
[self dismissModalViewControllerAnimated:YES];
}
}
UPDATE: this issue not reproduced in iOS5 but present at iOS 4.3
As you indicated. iOS 5 forwards the messages, where previous versions do not. Here's how I handle a similar situation:
- (BOOL)needsMessageForwarding:(UIViewController *)vc {
if ( [vc isKindOfClass:[UINavigationController class]] == NO)
return YES;
NSString *ver = [UIDevice currentDevice].systemVersion;
if ( [ver characterAtIndex:0 < '5'] )
return YES;
return NO;
}
- (void) viewWillAppear:(BOOL)animated {
...
if ( [self needsMessageForwarding:modalViewController] )
[modalViewController viewWillAppear:animated];
...
}
// repeat pattern in the other viewWill... viewDid... functions.
In my situation I have a list of view controllers that could be visible, so I manage which view controller is visible and forward the message to it.
Related
In my app we need only one view controller would be in all orientation mode other view controllers will be portrait mode only.
I am using below code and it's working perfectly but when coming back to pervious view controller it's not rotating in portrait mode when I am coming from Landscape mode.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
// Get topmost/visible view controller
UIViewController *currentViewController = [self topViewController];
// Check whether it implements a dummy methods called canRotate
if ([currentViewController respondsToSelector:#selector(canRotate)]) {
// Unlock landscape view orientations for this view controller
return UIInterfaceOrientationMaskAllButUpsideDown;
}
// Only allow portrait (standard behaviour)
return UIInterfaceOrientationMaskPortrait;
}
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
I've been working against the same issue. The orientation can be forced back to its normal configuration by adding an adjustment in viewWillAppear of the controller you are going back to:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
The app I'm working on is portrait oriented, but when a video is running (it is embed in a webview), I need to re-orient the video in landscape mode. How should I do that? I found a solution, which worked just fine until days ago :). I believe it's because iOS 7 updates, but I'm not sure. So, this is what I previously used, but it is not working anymore because window and class name are always nil.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
id presentedViewController = [window.rootViewController presentedViewController];
NSString *className = presentedViewController ? NSStringFromClass([presentedViewController class]) : nil;
if (window && [className isEqualToString:#"MPInlineVideoFullscreenViewController"]) {
return UIInterfaceOrientationMaskAll;
} else {
return UIInterfaceOrientationMaskPortrait;
}
I found a solution by myself, finally! I implemented the following method in AppDelegate and it worked. My problem was that, at first, I didn't check the right view controller.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
NSString *className = NSStringFromClass([window class]);
if ([((UINavigationController *)window.rootViewController) respondsToSelector:#selector(visibleViewController)]) {
className = NSStringFromClass([((UINavigationController *)window.rootViewController).visibleViewController class]);
}
if ([className isEqualToString:#"MPFullscreenWindow"] || [className isEqualToString:#"MPInlineVideoFullscreenViewController"]) {
return UIInterfaceOrientationMaskAll;
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
return UIInterfaceOrientationMaskLandscape;
} else {
return UIInterfaceOrientationMaskPortrait;
}
Here's a solution that will allow rotation on any additional windows presented in the iPhone app (such as a vide player) but remain landscape in an iPad app. Place it in your app delegate.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
return UIInterfaceOrientationMaskLandscape;
} else {
if (window == self.window
|| ![window isMemberOfClass:[UIWindow class]]) {
return UIInterfaceOrientationMaskPortrait;
}
if ([window isEqual:[[UIApplication sharedApplication] windows][1]]) {
// Rotate the secondary window.
return UIInterfaceOrientationMaskAllButUpsideDown;
}
return UIInterfaceOrientationMaskPortrait;
}
So I figured I'd share what my solution was. Actually branching off of the OP question, just modified it. Works for me on iOS 7 and 8.
My approach was different as I have a toggle switch in another view controller that enables portrait or landscape.
Anyways, here it is.
UPDATED:
Ok so the previous method broke the launch screen. Example: If you have your device in landscape, and launched but it's a portrait app, it will rotate, BUT, the window will get cut in half. Pain in the butt esp if you have some nice loading screens going on. Anyways, the replaced code below fixes that AND allows video rotation. Obviously not everybody will be using a rotation switch, just adjust accordingly.
//Allow video only rotation in portrait mode.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
//Switch for Rotation
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:#"Rotation"];
if (switchOn) {
window.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
[window setFrame:[[UIScreen mainScreen] bounds]]; //Add
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else {
id presentedViewController = [window.rootViewController presentedViewController];
NSString *className = presentedViewController ? NSStringFromClass([presentedViewController class]) : nil;
if ((window && [className isEqualToString:#"MPInlineVideoFullscreenViewController"]) ||
[className isEqualToString:#"MPMoviePlayerViewController"] ||
[className isEqualToString:#"AVFullScreenViewController"]) {
window.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
[window setFrame:[[UIScreen mainScreen] bounds]]; //Add
[window makeKeyAndVisible];
return UIInterfaceOrientationMaskAllButUpsideDown;
}
window.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
[window setFrame:[[UIScreen mainScreen] bounds]]; //Add
return UIInterfaceOrientationMaskPortrait;
}
self.window.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
[self.window setFrame:[[UIScreen mainScreen] bounds]]; //Add
[self.window makeKeyAndVisible];
}
UPDATED AGAIN:
So the previous edit I laid out had a weird flicker of the view below the movie player. This seems to have fixed that. Tested on 6+ device, and iOS 7/8 in the simulator.
Hope this helps somebody.
Swift 3, I sorted out on this way (your info.plist / project settings can have ONYL the portrait orientation checked) :
// MARK: - Orientation
extension AppDelegate {
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
// Let webView video to be rotated
if window != self.window {
return window?.rootViewController?.supportedInterfaceOrientations ?? .all;
}
// All other screens are portrait
return .portrait;
}
}
Try It....
-(BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
If you don't want your UIViewController to be able to rotate when the video isn't on the screen. Use this--
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if(webView && webView.superView) return YES;
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
This is very similar to how I solved for iOS 7, but this doesn't work for iOS 8. MPFullscreenWindow is no longer returned and Xcode complains about breaking constraints.
My solution seems to be fairly general, and takes care of some weird behavior on iOS 7 where window sometimes passed in as nil.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
return UIInterfaceOrientationMaskAll;
}
else
{
// when dismissing a view controller, the view controller being returned to isn't in control of the orientiation
// (shouldAutorotate and supportedInterfaceOrientations seem to be called, but they aren't observed then,
// rather only when the device is rotated after that view is fully showing)
// instead, the result of this method only is what's observed
// we could return different values depending on which view controller is frontmost, but currently it seems
// good enough to call supportedInterfaceOrientations of the frontmost view controller and return that
// on ios7, critical calls to this method are often passed window=nil, in that case use self.window instead
UIViewController *frontViewController = window ? window.rootViewController : self.window.rootViewController;
// special case only when transitioning to or from a presented view controller
if (frontViewController.presentedViewController &&
(frontViewController.presentedViewController.isBeingDismissed || frontViewController.presentedViewController.isBeingPresented))
{
if (frontViewController.presentedViewController && !frontViewController.presentedViewController.isBeingDismissed) {
frontViewController = frontViewController.presentedViewController;
}
if ([frontViewController isKindOfClass:[UINavigationController class]]) {
frontViewController = ((UINavigationController *)frontViewController).topViewController;
}
// return whatever the front view controller's supportedInterfaceOrientations returns, since it normally is ignored for some reason
return [frontViewController supportedInterfaceOrientations];
}
else
{
// return this normally, this gets intersected with the result of the front view controller's supportedInterfaceOrientations
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
}
=> Put below method inside your AppDelegate class, it allow to play video in landscape mode even when device orientation is locked to portrait mode only:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)windowx
{
if ([[self.window.rootViewController presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]] ||
[[self.window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(#"MPInlineVideoFullscreenViewController")])
{
if ([self.window.rootViewController presentedViewController].isBeingDismissed)
{
return UIInterfaceOrientationMaskPortrait;
}
else
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
else
{
return UIInterfaceOrientationMaskPortrait;
}
}
I am trying to disable the back gesture for my view controller using the following set of code.
In FirstViewController.m, I'm setting the delegate of interactivePopGestureRecognizer
- (void) viewWillLoad {
// Other stuff..
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
And then implementing the <UIGestureRecognizerDelegate> method and returning NO.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return NO;
}
And in dealloc I'm setting the delegate to nil. (I have read somewhere that in iOS 7, you have to manually set the delegates to nil)
- (void)dealloc {
self.navigationController.delegate = nil;
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
This works in the FirstViewController. But when I push SecondViewController to this, the gesture does not work on that either. How can I disable the gesture in FirstViewController only?
Also when I pop FirstViewController to go to RootViewController and then try to push FirstViewController again, I get the object deallocated error :
[FirstViewController gestureRecognizer:shouldReceiveTouch:]: message sent to deallocated instance 0x14ed0280
Why else do I need to do other than setting the delegates to nil? Or am I setting it in the wrong place?
Try the below untested code in your FirstViewController :
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
-(void) viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
I originally put these answers into a comment below the accepted answer, but I feel this needs to be said as an answer to get more visibility.
More often than not, you will find that the accepted answer does not work. This is because viewWillAppear: can be called before the view is added to a navigation controller's view hierarchy, and so self.navigationController is going to be nil. Because of this, the interactivePopGestureRecognizer may not be disabled in some cases. You're better off calling it in viewDidAppear: instead.
Here's code that will work (assuming your view controller is correctly added to a navigation controller's view hierarchy):
Objective-C
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[[self navigationController] interactivePopGestureRecognizer] setEnabled:NO];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[[self navigationController] interactivePopGestureRecognizer] setEnabled:YES];
}
Swift
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
navigationController?.interactivePopGestureRecognizer?.isEnabled = false
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.interactivePopGestureRecognizer?.isEnabled = true
}
I tried the all above but they did not work for me.So i tried this and it works for me on both IOS7 and IOS8.
Just make sure that your view controller implements this protocol i.e UIGestureRecognizerDelegate
and write the code given below.
-(void)viewWillAppear : (BOOL) animated {
[super viewWillAppear : animated];
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled =
NO;
self.navigationController.interactivePopGestureRecognizer.delegate =
self;
}
}
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([gestureRecognizer isEqual:self.navigationController.interactivePopGestureRecognizer]) {
return NO;
} else {
return YES;
}
}
I found out setting the gesture to disabled only doesn't always work. It does work, but for me it only did after I once used the backgesture. Second time it wouldn't trigger the backgesture. Furthermore, as John Rogers said, it's import to use the viewDidAppear and viewWillAppear as the navigationController else would be nil.
Fix for me was to delegate the gesture and implement the shouldbegin method to return NO:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Disable iOS 7 back gesture
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// Enable iOS 7 back gesture
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
return NO;
}
This just worked for me in xCode 7:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.navigationController!.interactivePopGestureRecognizer!.enabled = false
}
override func viewWillDisappear(animated: Bool) {
super.viewDidDisappear(animated)
self.navigationController!.interactivePopGestureRecognizer!.enabled = true
}
For only one view, I don't know the way... But I use the next code to disable fully the swipe gesture:
in your AppDelegate.m
if ([[UIDevice currentDevice].systemVersion floatValue] >= 7){
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
Is it possible to pop up an UIViewController (xib file) like UIPopOverControl in iPad ?
I have a separate NIB file which is linked to an UIViewController. I want to popup that NIB file along with the button pressed with a customised size (200,200).
Is this possible?
I am trying to get something like this on the iPhone - http://www.freeimagehosting.net/c219p
You can also use one of these custom made clases to show a popup:
https://github.com/sonsongithub/PopupView
https://github.com/werner77/WEPopover
https://github.com/50pixels/FPPopover
Example with FPPopover:
//the view controller you want to present as popover
YourViewController *controller = [[YourViewController alloc] init];
//our popover
FPPopoverController *popover = [[FPPopoverController alloc] initWithViewController:controller];
//the popover will be presented from the okButton view
[popover presentPopoverFromView:okButton];
//release if you arent using ARC
[controller release];
yes it is. load Your pOpOver controller lazily at the point when it is needed. add its view as a subview (you could animate the addition). make its frame size what You need and add the image You have shown as a background subview of the pOpOver controller along with other controls You want in the pop up.
good luck
UPDATE:
alright, ii will show You how ii do this in my app Lucid Reality Check (deployment target iOS4.3).
one can use a UIPopoverController to present another controllers view. what ii do first is to make sure ii always know the current orientation of the device, so ii can reposition the popup on rotation (maybe this works by itself on iOS6?). so in my base controller (from where ii want to show a popup) ii have an instance variable like this:
UIInterfaceOrientation toOrientation;
and also:
UIPopoverController *popover;
UIButton *popover_from_button;
BOOL representPopover;
popover will be reused for all popups, and popover_from_button will hold the button from which the popup is initiated.
then the next code comes into the base controller:
- (void)popoverWillRotate {
if ([popover isPopoverVisible]) {
[self dismissPopover];
representPopover = YES;
}
}
- (void)popoverDidRotate {
if (popover && representPopover) {
representPopover = NO;
[self representPopover];
}
}
these two methods have to be called every time the device is rotated, like this:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
//DLOG(#"willRotateTo %i", toInterfaceOrientation);
toOrientation = toInterfaceOrientation;
if ([Kriya isPad ]) {
[self popoverWillRotate];
}
}
as one can see, first the orientation is captured then popoverWillRotate is called. this would hide the popover during the orientation animation. and after rotating, the popover must be redisplayed like this:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
//DLOG(#"didRotateFrom %i", fromInterfaceOrientation);
//[self layout:toOrientation]; //do some layout if You need
if ([Kriya isPad]) {
[self popoverDidRotate];
}
}
- (void)layout:(UIInterfaceOrientation)toInterfaceOrientation {
//one can do view layout here, and call other controllers to do their layout too
}
now that the orientation changes are worked out, the code for presenting the popover arrives here:
#pragma mark Popovers
- (void)presentPopoverWith:(id)controller fromButton:(UIButton*)button {
if (popover)
[popover release];
if (popover_from_button)
[popover_from_button release];
popover_from_button = [button retain];
popover = [[UIPopoverController alloc] initWithContentViewController:controller];
[popover setDelegate:self];
[self representPopover];
}
- (void)representPopover{
if (popover) {
UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirectionAny;
UIViewController *vc = (UIViewController*)[popover contentViewController];
CGSize contentSize = [vc contentSizeForViewInPopover];
if (contentSize.width > 0 && contentSize.height > 0) {
[popover setPopoverContentSize:contentSize animated:NO];
}
//DLOG(#"representPopover rect:%#", [Kriya printRect:popover_from_button.frame]);
[popover presentPopoverFromRect:CGRectOffset(popover_from_button.frame, 0, popover_from_button.frame.size.height + 7.0) inView:self.view permittedArrowDirections:arrowDirection animated:YES];
}
}
- (void)dismissPopover {
if (popover) {
[popover dismissPopoverAnimated:YES];
}
}
finally, if one wants to be notified when the popover is dismissed, the base controller must implement a delegate method:
#pragma mark UIPopoverControllerDelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
//do something important here like drink some water
}
and don't forget to make the base controller a UIPopoverControllerDelegate in its header.
a use case for this way of doing popups would then look like this:
- (void)takeImage {
UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
[picker setDelegate:self];
[picker setAllowsEditing:NO];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[picker setSourceType:UIImagePickerControllerSourceTypeCamera];
if ([Kriya isPad]) {
[self presentPopoverWith:picker fromButton:backgroundImageButton];
} else {
//modals on iPhone/iPod
//DLOG(#"takeImage addSubview picker");
[self presentModalViewController:picker animated:YES];
}
} else {
//DLOG(#"no camera");
}
}
this would use an image picker as the content for the popup, but one can use any controller with a valid view. so just do this:
[self presentPopoverWith:popupsContentController fromButton:tappedButton];
one should not have any missing information, :), the method [Kriya isPad] is just this:
+ (BOOL)isPad {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
// iPad capable OS
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
//this is an iPad
return YES;
}else {
//this is an iPod/iPhone
return NO;
}
#else
//can not pissible be iPad
return NO;
#endif
}
ENJOY!
I have a MainViewController which has a button which pushes a new view (InfoViewController), via flip horizontailly. like so:
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
The MainView Controller supports Portrait and PortraitUpsideDown. Like so:
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait |
UIInterfaceOrientationMaskPortraitUpsideDown);
}
In my InfoViewController it also states the above code. In my AppDelegate it has this in the LaunchOptions:
[self.window setRootViewController:self.mainViewController];
In my app.plist file it supports all orientations. This is because other views need to support landscape as well. So On my MainViewController and InfoViewController I need only Portrait and PortraitUpsideDown. But on another view I need all orintations.
My MainViewController works fine, but my InfoViewController is working for all orientations.
I am having extreme diffulty trying to get this to work in iOS6. I have researched other posts and tried the assistance other people have provided, but had no luck whatsoever. Please can someone help me acheive this thank you. And I'm a Objective-C newbie :p
Don´t support all orientations in your app plist file, only those that your root view controller supports.
Autorotation is changing in iOS 6. In iOS 6, the shouldAutorotateToInterfaceOrientation: method of UIViewController is deprecated. In its place, you should use the supportedInterfaceOrientationsForWindow: and shouldAutorotate methods:
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
Modal ViewControllers no longer get rotation calls in iOS 6:
The willRotateToInterfaceOrientation:duration:,
willAnimateRotationToInterfaceOrientation:duration:, and
didRotateFromInterfaceOrientation: methods are no longer called on any view controller that makes a full-screen presentation over
itself—for example those that are called with: presentViewController:animated:completion:.
You can let the view controller that presents your modal view controller inform it of rotation.
Also, now you use: presentViewController:animated:completion: to present the view controller. presentModalViewController:animated: is deprecated which you use in the code.
I have solved similar problems, while using tab bar controller.
Subclass UITabBarController. Implement these methods:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (BOOL)shouldAutorotate
{
NSLog(#"Orientation:%d", [[UIDevice currentDevice] orientation]);
for (UIViewController *viewController in self.viewControllers) {
[viewController shouldAutorotate];
}
return YES;
}
If you want to handle rotations in controllers inside tabbarcontroller, in each of the controllers in the tab bar controller implement those methods too and write code to handle orientation change. If you don't want to handle it, then you don't need to implement those methods. TabBarControllers methods will always run when orientation changes. Even twice for unknown reason.
Yes, and don't forget to delete all shouldAutorotate methods. I moved to the new orientation model completely. If you want to make them remain, probably, it will be harder.
Make a category by subclassing UINavigationController and implement following methodes
in .h file
-(BOOL)shouldAutorotate;
-(NSUInteger)supportedInterfaceOrientations;
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
in .m file
-(BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
and implement following methodes in the view controller class ,class u want to enable rotation
-(NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown);
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
add this code on Subclass UITabBarController .m
#implementation UINavigationController (rotation)
//temp hack for iOS6, this allows passing supportedInterfaceOrientations to child viewcontrollers.
- (NSUInteger)supportedInterfaceOrientations {
return [self.topViewController supportedInterfaceOrientations];
}
#end
#implementation NameClassUITabBar
- (void)viewDidLoad {
[super viewDidLoad];
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
#end
Here I've posted my solution/experince in tab bar controller with rotations:
http://luterr.blogspot.sg/2015/04/example-code-uiinterfaceorientationmask.html