Gamecenter authentication in landscape only Cocos2d with CCLayer for iOS 6 - iphone

I'm having what seems to be a fairly common problem, but my searches and implementations of solutions have not worked out.
I've built a Cocos2d game that is intended to be landscape only, but needs to access Gamecenter. Gamecenter is working, with portrait mode enabled, but it's also allowing the game to flip to portrait mode too.
I've attempted the following fixes:
Game center login lock in landscape only in i OS 6
GameCenter authentication in landscape-only app throws UIApplicationInvalidInterfaceOrientation
Error in iOS 6 after adding GameCenter to a landscape-only cocos2d app
Cocos 2d 2.0 shouldAutorotate not working?
I believe the problem is that I've built the game using CCLayers instead of UIViewControllers
Example:
MenuLayer.h
#interface MenuLayer : CCLayer <GKAchievementViewControllerDelegate, GKLeaderboardViewControllerDelegate, UINavigationControllerDelegate>{
..my header info..
}
MenuLayer.m
...
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
-(BOOL)shouldAutorotate {
return [[UIDevice currentDevice] orientation] != UIInterfaceOrientationPortrait;
}
-(void)authenticateLocalPlayer
{
GKLocalPlayer * localPlayer= [GKLocalPlayer localPlayer];
if(localPlayer.authenticated == NO)
{
NSString *reqSysVer = #"6.0";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
{
[[GKLocalPlayer localPlayer] setAuthenticateHandler:(^(UIViewController* viewcontroller, NSError *error) {
if (viewcontroller != nil) {
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] presentModalViewController:viewcontroller animated:YES];
}else if ([GKLocalPlayer localPlayer].authenticated)
{
//do some stuff
}
})];
}
else
{
[localPlayer authenticateWithCompletionHandler:^(NSError *error){
if(localPlayer.isAuthenticated)
{
//Peform Additionl Tasks for the authenticated player.
}
}];
}
}
}
...
Since I've built the game using CCLayers instead of UIViewControllers, what alternatives do I have? Am I correct in assuming that CCLayers don't call use supportedInterfaceOrientations or shouldAutorotate?
Or am I supposed be changing this code somehow to fix the problem:
// Create a Navigation Controller with the Director
navController_ = [[UINavigationController alloc] initWithRootViewController:director_];
navController_.navigationBarHidden = YES;

This frustrated me for awhile too. After digging around for awhile on the 'Net I found a couple of sources and some worked with iOS 6, some with iOS5, but I had to make some modifications so that it worked the way I wanted on both iOS5 and iOS6. This is the code I am using, it works on my iPhone using 5.1 and 6. Note that the Game Center login still comes up in portrait orientation, there doesn't appear to be anything you can do about that. But the rest of the game will remain in landscape mode.
enable portrait mode as a supported orientation in your build settings (info.plist).
Create a new subclass of UINavigationController. Name this class whatever makes sense to you.
In your AppDelegate, include your new custom UINavigationController header file.
In your App Delegate, comment out the original call and instead call your custom class.
That should do the trick. Here is the code from my custom class:
#import <UIKit/UIKit.h>
#interface CustomNavigationViewController : UINavigationController
-(UIInterfaceOrientation) getCurrentOrientation;
#end
And the implementation file:
#import "CustomNavigationViewController.h"
#interface CustomNavigationViewController ()
#end
#implementation CustomNavigationViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// This is required to allow GameCenter to login in portrait mode, but only allow landscape mode for the rest of the game play/
// Arrrgg!
-(BOOL) shouldAutorotate {
return YES;
}
-(NSUInteger) supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
-(UIInterfaceOrientation) preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight; // or left if you prefer
}
-(NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
return UIInterfaceOrientationMaskLandscape;
else {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return [[UIDevice currentDevice] orientation] != UIInterfaceOrientationPortrait;
}
-(UIInterfaceOrientation) getCurrentOrientation {
return [[UIDevice currentDevice] orientation];
}
#end
Note that last method getCurrentOrientation isn't required I just put that in there in case I wanted to determine what the current orientation is.
The custom class is called in AppDelegate.m like this: (comment out the original code)
navController = [[CustomNavigationViewController alloc] initWithRootViewController:director];
window.rootViewController = navController;
navController.navigationBarHidden = YES;
[window makeKeyAndVisible];
Hope this helps.

Related

How to block rotation in ios 7

I used this code to block the rotation before ios 7 (i was also using xibs, now storyboard)
- (BOOL)shouldAutorotate {
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationPortrait;
}
now that i migrated to storyboard and ios7 it is not working, my view is still rotating.
UPDATE:
I solved this by adding this code to the delegate, now my previous code works like charm
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
if (self.fullScreenVideoIsPlaying) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else {
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
Atrik's code worked. Here is a more complete solution which allows locking and unlocking of portrait-mode-only even with the use of UINavigationController
appdelegate .h
#property (nonatomic) BOOL screenIsPortraitOnly;
appdelegate .m
#pragma mark - View Orientation
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
if (self.screenIsPortraitOnly) {
return UIInterfaceOrientationMaskPortrait;
}
else {
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
}
For all view controllers where I need Portrait Lock
If you haven't used a subclass which has the app delegate imported then don't forget to import the delegate. For most view controllers I use a subclass of UIViewController which at least does importation.
#import "AppDelegate.h"
I use this for all portrait locked viewcontrollers.
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:true];
[self portraitLock];
}
-(void) portraitLock {
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.screenIsPortraitOnly = true;
}
#pragma mark - interface posiiton
- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL) shouldAutorotate {
return NO;
}
ViewDidLoad runs before viewDidAppear so I run this in my subclass of UIViewController to unlock all screens. The viewWillAppear with the lock method is used only in the cotrollers which I need to lock the screen.
- (void)viewDidLoad
{
[super viewDidLoad];
[self portraitUnLock];
}
-(void) portraitUnLock {
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.screenIsPortraitOnly = false;
}
If you only want in landscape mode then you can do it with xcode project setting
go to Target > summary > support interface orientations
Or you can do a code
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
In XCode 5, which is required to be used for iOS7 development, you can go to your target and under Deployment Info uncheck everything except Portrait for device orientation.
If you don't want your app to rotate at all (no matter which view is active), you can click on your project in the Xcode sidebar, scroll down, and deselect Landscape Left and Landscape Right.

How can I make a video display in Landscape mode on iOS 5?

I'm having a very strange problem. I want a video to appear in landscape mode, but I can't seem to make it work. Even if I can't make it always show Landscape, at least I want it to show ok, and I can't make that either!! Here is my code:
#import "SplashViewController.h"
#import "MainViewController.h"
#import "MediaPlayer/MediaPlayer.h"
#interface SplashViewController ()
#property (nonatomic, retain) NSTimer *timer;
#end
#implementation SplashViewController
#synthesize timer = _timer;
-(BOOL)shouldAutorotateToInterfaceOrientation:UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
- (id)init
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self = [self initWithNibName:#"SplashViewController_iPhone" bundle:nil];
} else {
self = [self initWithNibName:#"SplashViewController_iPad" bundle:nil];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSString *url = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"intro.mp4"];
playerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL fileURLWithPath:url]];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:[playerViewController moviePlayer]];
[playerViewController shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationLandscapeRight];
[self.view addSubview:playerViewController.view];
//play movie
MPMoviePlayerController *player = [playerViewController moviePlayer];
player.scalingMode = MPMovieScalingModeAspectFill;
[player play];
}
- (void) movieFinishedCallback:(NSNotification*) aNotification {
MPMoviePlayerController *player = [aNotification object];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[player stop];
[player.view removeFromSuperview];
[self loadMainView];
}
- (void)loadMainView
{
MainViewController *mainVC = [[MainViewController alloc] init];
[self.navigationController pushViewController:mainVC animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
And here comes the weirdness...
If I start the app with my iPad physically in Landscape Mode, the video shows like this (please not that the bar at the top is shorter than the widht! :O)
If I then rotate the iPad to Portrait, it looks like this:
But then, if I start the app with my iPad physically in Portrait Mode, the video shows like this:
And if I then rotate the iPad to Landscape, it looks like this:
Which is GREAT! This final image is what I would like the video to always look like.
Any ideas what I might be doing wrong???
Thanks!
EDIT 1
Ok, with #Tark answer I was able to fix the player display issue. Now it's showing fine no matter how I start the app. Thanks for that!! What is missing now is the always landscape mode.
I tried with the following methods:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation==UIInterfaceOrientationLandscapeRight)
return YES;
return NO;
}
I also tried inserting the row
Initial interface orientation = Landscape (right home button)
In the Info.plist
What I'm getting is that if I start the app in Landscape mode, if I rotate the iPad to Portrait, it stays in Landscape. GREAT!
But if I start the app in Portrait mode, the video shows in Portrait mode. Once I rotate it to Landscape, I can't rotate it back to Portrait, which is good, but I don't want it to start in Portrait!
EDIT 2
Ok, now this is even more weird. If I try it on an iPhone, it works great. No matter if I start the app in Landscape or Portrait, the video is shown always in Landscape.
But if I try it on an iPad, the problem in EDIT 1 arises... :S
Any ideas?
Thanks!
Have you tried setting the frame of the MPMoviePlayerViewControllers view when you add it as a subview?
...
playerViewController.view.frame = self.view.bounds;
[self.view addSubview:playerViewController.view];
...
To make the app only run in landscape mode, you should make sure that you have only selected the orientations you want in the app plist. In Xcode 4 there is a handy Supported Interface Orientations section in the target settings, make sure you only select landscape here. If you still have the issue, you have to make sure that you are disabling autorotation on all visible controllers in the view stack.
shouldAutorotateToInterfaceOrientation is deprecated as of iOS 6, Have you tried using supportedInterfaceOrientations?
If you are trying to support iOS 5 & 6 then I believe you need to use both:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
I haven't tested this so take it for what it's worth.

IOS 6 force device orientation to landscape

I gave an app with say 10 view controllers. I use navigation controller to load/unload them.
All but one are in portrait mode. Suppose the 7th VC is in landscape. I need it to be presented in landscape when it gets loaded.
Please suggest a way to force the orientation go from portrait to landscape in IOS 6 (and it will be good to work in IOS 5 as well).
Here is how I was doing it BEFORE IOS 6:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UIViewController *c = [[[UIViewController alloc]init] autorelease];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
Presenting and dismissing a modal VC was forcing the app to review its orientation, so shouldAutorotateToInterfaceOrientation was getting called.
What I have have tried in IOS 6:
- (BOOL)shouldAutorotate{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationLandscapeLeft;
}
On load, the controller keeps staying in portrait. After rotating the device, the orientation changes just ok. But I need to make the controller to rotate automatically to landscape on load, thus the user will have to rotate the device to see the data correctly.
Another problem: after rotating the device back to portrait, the orientation goes to portrait, although I have specified in supportedInterfaceOrientations only UIInterfaceOrientationMaskLandscape. Why it happens?
Also, NONE of above 3 methods are getting called.
Some (useful) data:
In my plist file I have specified 3 orientations - all but upside down.
The project was started in Xcode 4.3 IOS 5. All classes including xibs were created before Xcode 4.5 IOS 6, now I use the last version.
In plist file the status bar is set to visible.
In xib file (the one I want to be in landscape) the status bar is "None", the orientation is set to landscape.
Any help is appreciated. Thanks.
Ok, folks, I will post my solution.
What I have:
A view based application, with several view controllers. (It was navigation based, but I had to make it view based, due to orientation issues).
All view controllers are portrait, except one - landscapeLeft.
Tasks:
One of my view controllers must automatically rotate to landscape, no matter how the user holds the device. All other controllers must be portrait, and after leaving the landscape controller, the app must force rotate to portrait, no matter, again, how the user holds the device.
This must work as on IOS 6.x as on IOS 5.x
Go!
(Update Removed the macros suggested by #Ivan Vučica)
In all your PORTRAIT view controllers override autorotation methods like this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
You can see the 2 approaches: one for IOS 5 and another For IOS 6.
The same for your LANDSCAPE view controller, with some additions and changes:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
[image_signature setImage:[self resizeImage:image_signature.image]];
return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
[image_signature setImage:[self resizeImage:image_signature.image]];
return UIInterfaceOrientationMaskLandscapeLeft;
}
ATTENTION: to force autorotation in IOS 5 you should add this:
- (void)viewDidLoad{
[super viewDidLoad];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];
}
Analogically, after you leave the LANDSCAPE controller, whatever controller you load, you should force again autorotation for IOS 5, but now you will use UIDeviceOrientationPortrait, as you go to a PORTRAIT controller:
- (void)viewDidLoad{
[super viewDidLoad];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];
}
Now the last thing (and it's a bit weird) - you have to change the way you switch from a controller to another, depending on the IOS:
Make an NSObject class "Schalter" ("Switch" from German).
In Schalter.h say:
#import <Foundation/Foundation.h>
#interface Schalter : NSObject
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease;
#end
In Schalter.m say:
#import "Schalter.h"
#import "AppDelegate.h"
#implementation Schalter
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease{
//adjust the frame of the new controller
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
CGRect windowFrame = [[UIScreen mainScreen] bounds];
CGRect firstViewFrame = CGRectMake(statusBarFrame.origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height);
VControllerToLoad.view.frame = firstViewFrame;
//check version and go
if (IOS_OLDER_THAN_6)
[((AppDelegate*)[UIApplication sharedApplication].delegate).window addSubview:VControllerToLoad.view];
else
[((AppDelegate*)[UIApplication sharedApplication].delegate).window setRootViewController:VControllerToLoad];
//kill the previous view controller
[VControllerToRelease.view removeFromSuperview];
}
#end
NOW, this is the way you use Schalter ( suppose you go from Warehouse controller to Products controller ) :
#import "Warehouse.h"
#import "Products.h"
#implementation Warehouse
Products *instance_to_products;
- (void)goToProducts{
instance_to_products = [[Products alloc] init];
[Schalter loadController:instance_to_products andRelease:self];
}
bla-bla-bla your methods
#end
Of course you must release instance_to_products object:
- (void)dealloc{
[instance_to_products release];
[super dealloc];
}
Well, this is it. Don't hesitate to downvote, I don't care. This is for the ones who are looking for solutions, not for reputation.
Cheers!
Sava Mazare.
This should work, it's similar to the pre-iOS 6 version, but with a UINavigationController:
UIViewController *portraitViewController = [[UIViewController alloc] init];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:portraitViewController];
[self.navigationController presentModalViewController:nc animated:NO];
[self.navigationController dismissModalViewControllerAnimated:NO];
I'm calling this before I'm pushing the next UIViewController. It will force the next pushed UIViewController to be displayed in Portrait mode even if the current UIViewController is in Landscape (should work for Portrait to Landscape too). Works on iOS 4+5+6 for me.
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 my VC I 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)
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
second one thats tells your VC which is preferred interface orientation when VC is going to be displayed.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
Just change Portrait for orientation that you want ;)
This solution is working smooth, I don't like the idea of creating macros and other stuff, that goes around this simple solution.
Hope this help...
I had the same problem, 27 views in my application from which 26 in portrait and only one in all orientations ( an image viewer :) ).
Adding the macro on every class and replace the navigation wasn't a solution I was comfortable with...
So, i wanted to keep the UINavigationController mechanics in my app and not replace this with other code.
What to do:
#1 In the application delegate in method didFinishLaunchingWithOptions
if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
// how the view was configured before IOS6
[self.window addSubview: navigationController.view];
[self.window makeKeyAndVisible];
}
else
{
// this is the code that will start the interface to rotate once again
[self.window setRootViewController: self.navigationController];
}
#2
Because the navigationController will just responde with YES for autorotation we need to add some limitations:
Extend the UINavicationController -> YourNavigationController and link it in the Interface Builder.
#3 Override the "anoying new methods" from navigation controller.
Since this class is custom only for this application it can take responsibility
for it's controllers and respond in their place.
-(BOOL)shouldAutorotate {
if ([self.viewControllers firstObject] == YourObject)
{
return YES;
}
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
if ([self.viewControllers firstObject] == YourObject)
{
return UIINterfaceOrientationMaskLandscape;
}
return UIInterfaceOrientationMaskPortrait;
}
I hope this will help you,
From the iOS 6 Release Notes:
Now, iOS containers (such as UINavigationController) do not consult their children to determine whether they should autorotate.
Does your rootViewController pass the shouldAutoRotate message down the ViewController hierarchy to your VC?
I used the same method as OP pre-ios6 (present and dismiss a modal VC) to show a single view controller in landscape mode (all others in portrait). It broke in ios6 with the landscape VC showing in portrait.
To fix it, I just added the preferredInterfaceOrientationForPresentation method in the landscape VC. Seems to work fine for os 5 and os 6 now.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
- (BOOL)shouldAutorotate
{
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
Hey guys after tryng a lot of different possible solutions with no success i came out with the following solution hope it helps!.
I prepared a recipe :).
Problem:
you need change orientation of viewcontrollers using navigationcontroller in ios 6.
Solution:
step 1. one initial UIviewcontroler to trigger modal segues to landscape and
portrait UInavigationControllers as picture shows....
more deeply in UIViewController1 we need 2 segues actions according to global variable at Appdelegate....
-(void)viewDidAppear:(BOOL)animated{
if([globalDelegate changeOrientation]==0){
[self performSegueWithIdentifier:#"p" sender:self];
}
else{
[self performSegueWithIdentifier:#"l" sender:self];
}
}
also we need a way back to portrait &| landscape....
- (IBAction)dimis:(id)sender {
[globalDelegate setChangeOrientation:0];
[self dismissViewControllerAnimated:NO completion:nil];
}
step 2. the first Pushed UiViewControllers at each NavigationController goes
with...
-(NSUInteger)supportedInterfaceOrientations{
return [self.navigationController supportedInterfaceOrientations];
}
-(BOOL)shouldAutorotate{
return YES;
}
step 3. We overwrite supportedInterfaceOrientations method at subclass of UInavigationController....
in your customNavigationController we have .....
-(NSUInteger)supportedInterfaceOrientations{
if([self.visibleViewController isKindOfClass:[ViewController2 class]]){
return UIInterfaceOrientationMaskPortrait;
}
else{
return UIInterfaceOrientationMaskLandscape;
}
}
step 4. At storyboard or by code, set wantsFullScreenLayout flag to yes, to both portrait and landscape uinavigationcontrollers.
Try segueing to a UINavigationController which uses a category or is subclassed to specify the desired orientation, then segue to the desired VC. Read more here.
As an alternative you can do the same using blocks:
UIViewController *viewController = [[UIViewController alloc] init];
viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:viewController animated:NO completion:^{
[self dismissViewControllerAnimated:NO completion:nil];
}];
Also, call it before pushing the new view.
Go to you Info.plist file and make the change
I had the same problem. If you want to force a particular view controller to appear in landscape, do it right before you push it into the navigation stack.
UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if (currentOrientation == UIInterfaceOrientationPortrait ||
currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];
UIViewController *vc = [[UIViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
I solved it by subclassing UINavigationController and overriding the supportedInterfaceOrientations of the navigation Controller as follow:
- (NSUInteger)supportedInterfaceOrientations
{
return [[self topViewController] supportedInterfaceOrientations];
}
All the controllers implemented supportedInterfaceOrientations with their desired orientations.
I have used the following solution. In the one view controller that has a different orientation than all the others, I added an orientation check in the prepareForSegue method. If the destination view controller needs a different interface orientation than the current one displayed, then a message is sent that forces the interface to rotate during the seque.
#import <objc/message.h>
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if(UIDeviceOrientationIsLandscape(self.interfaceOrientation))
{
UIInterfaceOrientation destinationOrientation;
if ([[segue destinationViewController] isKindOfClass:[UINavigationController class]])
{
UINavigationController *navController = (UINavigationController *)[segue destinationViewController];
destinationOrientation = [navController.topViewController preferredInterfaceOrientationForPresentation];
} else
{
destinationOrientation = [[segue destinationViewController] preferredInterfaceOrientationForPresentation];
}
if ( destinationOrientation == UIInterfaceOrientationPortrait )
{
if ([[UIDevice currentDevice] respondsToSelector:#selector(setOrientation:)])
{
objc_msgSend([UIDevice currentDevice], #selector(setOrientation:), UIInterfaceOrientationPortrait );
}
}
}
}

MPMoviePlayerController full screen orientation issue

My app supports only Landscape. I've added an MPMoviePlayerController to the view of my view controller.
When I press full screen button, it works fine and it will rotate in Landscape only for iOS versions prior to iOS 5. However, in iOS 5.0+, it also supports portrait (only when I enter into full screen mode).
How can I prevent portrait support in iOS 5.0 and above?
Try subclassing MPMoviePlayerViewController and overriding the shouldAutorotatoToInterfaceOrientation method to only support landscape modes:
-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if((toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight))
{
return true;
}
else
{
return false;
}
}
I resolved this problem thus: create custom navigation controller what support 2 orientation:
UIInterfaceOrientationLandscapeLeft && UIInterfaceOrientationLandscapeRight
More details:
1. Create custom navigation controller
CustomNavigationController.h file
#import <UIKit/UIKit.h>
#interface CustomNavigationController : UINavigationController
-(CustomNavigationController*)initWithRootViewController:(UIViewController *)rootViewController;
#end
CustomNavigationController.m file
#implementation IORNavigationController
-(CustomNavigationController*)initWithRootViewController:(UIViewController *)rootViewController
{
self = [super initWithRootViewController:rootViewController];
if (self)
{
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
2.In Appdelegate add self navigation controller
Appdelegate.h
#property (nonatomic, retain) CustomNavigationController* navigationController;
Appdelegate.m
self.navigationController = [[[CustomNavigationController alloc] initWithRootViewController:start] autorelease];
self.navigationController.view.autoresizesSubviews = YES;
window.rootViewController = self.navigationController;
[self.navigationController setNavigationBarHidden:YES];
And now you have app with two orientation and video in landscape orientation.

iOS - QLPreviewController - How to stop QuickLook from Rotating?

I have QuickLook (QLPreviewController) almost working how I want it, but because of the images characteristics I don't want it to rotate into portrait orientation.I have it configured in the "shouldAutoRotateToInterfaceOrientation" method to only return yes for landscape rotations (see code below for details) but it is still rotating to portrait.
Note: The shouldAutoRotateToInterfaceOrientation is a direct copy that is used in all of my view controllers for this project and it is working in the other view controllers.
//
// documentViewer.m
//
#import "DocumentViewer.h"
#implementation DocumentViewer
#synthesize documents;
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
return YES;
else if (interfaceOrientation == UIInterfaceOrientationLandscapeRight)
return YES;
else
return NO;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
//-(void)viewWillAppear:(BOOL)animated {
//
// self.userInteractionEnabled = YES;
//}
//Nessary for Enabling User Interaction
- (BOOL)canBecomeFirstResponder {
return YES;
}
-(void) createList:(NSString *) document {
documents = [[NSArray arrayWithObjects:document, nil] retain];
}
-(NSInteger) numberOfPreviewItemsInPreviewController: (QLPreviewController *) controller {
return [documents count];
}
- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index {
return [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[documents objectAtIndex:index] ofType:nil]];
}
#end
In AppDelegate.m replace
return UIInterfaceOrientationMaskAll;
with
return UIInterfaceOrientationMaskLandscape;
just like this:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskLandscape;
}
According to the ViewController Programming Guide for iOS, the autorotation is roughly controlled by the ViewController that was most recently made visible.
In your case that's probably the QLPreviewController itself, not your DocumentViewer. (And you say that the latter's shouldAutorotateToInterfaceOrientation: isn't called, which is consistent with this hypothesis).
So the autorotation is controlled by the shouldAutorotateToInterfaceOrientation: method of QLPreviewController, which in a little experiment of mine seems to allow everything but upside-down orientation.
So what you can do is define a subclass of QLPreviewController that only overrides shouldAutorotateToInterfaceOrientation: the way you did in DocumentViewer and use this subclass instead of the original QLPreviewController.
LandscapeOnlyQLPreviewController.h:
#import <QuickLook/QuickLook.h>
#interface LandscapeOnlyQLPreviewController : QLPreviewController {
}
#end
LandscapeOnlyQLPreviewController.m:
#import "LandscapeOnlyQLPreviewController.h"
#implementation LandscapeOnlyQLPreviewController
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
#end
I never did find a good answer, so I ended up just using a UIWebView.
But I'm still looking.
Try this:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}