Cocos2d version: v0.99.04
I'm adding Game Center to my current application and I found some code to open up the GKMatchmakerViewController. It seems to work well, except when it gets dismissed it changes the orientation in the simulator to portrait. The game only runs in landscape. I rotate the device back to landscape and all the cocos2d scenes still work fine, but if I open up an alert or peer picker, they open in portrait mode. I can open and close scenes, but they will now all display this behavior. This happens using an actual device also.
// *.h
UIViewController *tempVC;
// *.m
// Open
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = 2;
request.maxPlayers = 2;
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = self;
tempVC=[[UIViewController alloc] init];
[[[CCDirector sharedDirector] openGLView] addSubview:tempVC.view];
[tempVC presentModalViewController: mmvc animated: YES];
// Close
[tempVC dismissModalViewControllerAnimated:YES];
[tempVC.view removeFromSuperview];
[tempVC release];
As soon as I hit the dismissModalViewControllerAnimated, that's when the simulator rotates.
Thanks in advance for any help.
I had the same problem (not using cocos2d) and I solved it by subclassing the UIViewController that the Game Center is attached to:
#interface GameCenterViewController : UIViewController
{
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation;
#end
#implementation GameCenterViewController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
// Does it match my screenOrientation?
if (sceneOrientation == (UIDeviceOrientation)toInterfaceOrientation)
return YES;
return NO;
}
#end
Put this in AppDelegate.m before #implementation
#interface UINavigationController (Private)
- (NSUInteger)supportedInterfaceOrientations;
- (BOOL)shouldAutorotate;
#end
#implementation UINavigationController (Private)
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotate
{
return YES;
}
#end
Related
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"];
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];
I have the following code in my main ViewController viewDidLoad function
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
nav = [[NavWithAutoRotateViewController alloc] initWithRootViewController:self];
[window addSubview:[nav view]];
[window makeKeyAndVisible];
[[self navigationController] setNavigationBarHidden:YES];
My ipad app is currently set to only work in landscape mode and I'm using this new window to show a quicklook document and allowing the nav bar to provide a back button and save options for the document. Main problem is that the new UIWindow orientation doesn't match my main applications UIWindow.
I have a custom UINavigationController above called NavWithAutoRotateController and here is the code for that controller.
-(id)init
{
if(self)
{
// _supportedInterfaceOrientatoin = UIInterfaceOrientationMaskLandscape;
// _orientation = UIInterfaceOrientationLandscapeLeft;
}
return self;
}
- (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.
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft;
}
// Tell the system which initial orientation we want to have
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationMaskLandscape;
}
I think I have a solution. The problem seems to be in the assignment of UIViewController to the rootViewController in your extra UIWindow.
If you just assume that you can use the same view controller that your primary UIWindow is using, and then add things as subviews of the new UIWindow, there are orientation issues.
To solve this, I did the following:
UIWindow *newWindow = [[UIWindow alloc] initWithFrame: [UIApplication sharedApplication].keyWindow.frame];
newWindow.windowLevel = UIWindowLevelStatusBar+1;
// You can use a view controller instantiated from a xib or storyboard here if you want.
// Just don't use the view controller already set as a UIWindow's rootViewController.
UIViewController *newViewController = [[UIViewController alloc] init];
newWindow.rootViewController = newViewController;
[newWindow makeKeyAndVisible];
// Add something to the new UIWindow. Can use the new UIViewController's view:
[newViewController.view addSubview: myContentView];
// Or could add it as subview of UIWindow: - either works.
[newWindow addSubview: myContentView];
Doing it this way seems to have solved all the weird issues around rotation.
Hope this helps.
I was having the same problem. Orientation changes were being handled properly using the viewWillTransition method. But my problem was that in some edge case conditions, namely if my device was sitting at an odd angle, the custom UIWindow would initialize in portrait orientation, even though the rootViewController was in landscape. And viewWillTransition isn't called because the device isn't rotated on initial load. I found a really simple solution to my problem that worked in any situation I tested.
First initialize your custom UIWindow without a frame. Then set your frame. And voila.. its orientation is what you'd expect.
Swift
let customWindow = UIWindow()
customWindow.frame = CGRect(x: x, y: y, width: w, height: h)
customWindow.rootViewController = self //<your_viewController>
customWindow.windowLevel = .statusBar // or whatever level you need
customWindow.makeKeyAndVisible()
ObjC
UIWindow customWindow = [[UIWindow alloc] init];
customWindow.frame = CGRectMake(x, y, w, h);
customWindow.rootViewController = self;
customWindow.windowLevel = UIWindowLevelStatusBar;
[customWindow makeKeyAndVisible];
Register for status bar frame change notification which is only called (afaik) when orientation changes and then define your new window's orientation..
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(appWillChangeStatusBarFrameNotification:)
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
XCode 4.5.1, Application windows are expected to have a root view controller at the end of application launch
I'm a total noob in IOS app developing.
I use Xcode 4.5.1 with no storyboard.
I'm upgrading an IOS 4 app because it fails to run correctly on IOS 6 devices.
main view containing a question and five answers run once and stops there after user commit by pressing a button with the wanted answer, it should then reload itself with a new question and a new set of questions.
I get the infamous "Application windows are expected to have a root view controller at the end of application launch" in log output.
I've read and tried all comments and solutions in 7520971 but to no avail... still getting error and it seems to prevent me to load the view correctly.
here's what in my appDelegate.h
/*
* AnimViewAppDelegate.h
* AnimView
*
* Created by Administrateur local on 11-01-19.
* Copyright 2011 __MyCompanyName__. All rights reserved.
*
*/
#import <UIKit/UIKit.h>
#import "RootNavigationController.h"
#interface PPScaleAppDelegate : NSObject <UIScrollViewDelegate> {
UIWindow *window;
RootNavigationController *RootNavigationViewController;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) RootNavigationController *RootNavigationViewController;
#end
my appDelegate.m
//
// AnimViewAppDelegate.m
// AnimView
//
// Created by Administrateur local on 11-01-19.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "PPScaleAppDelegate.h"
#import "QuestionView.h"
#implementation PPScaleAppDelegate
#synthesize window;
#synthesize RootNavigationViewController;
//- (void)applicationDidFinishLaunching:(UIApplication *)application {
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Create the main screen
//CGRect frame = [[UIScreen mainScreen] bounds];
//self.window = [[UIWindow alloc] initWithFrame:frame];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; //2012
//Create the main view controller
RootNavigationViewController = [[RootNavigationController alloc] initWithNibName:NULL bundle:NULL];
//[window addSubview:RootNavigationViewController.view];
[self.window setRootViewController:RootNavigationViewController];
//Show the main window
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[window release];
[super dealloc];
}
#end
.h
//
// RootNavigationController.h
// IPhonePPS
//
// Created by Administrateur local on 11-02-11.
// Copyright 2011 Le Groupe CDGI Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "QuestionView.h"
#import "ResultView.h"
#import "ResultTableView.h"
#interface RootNavigationController : UINavigationController {
QuestionView *QuestionViewController;
ResultView *ResultViewController;
ResultTableView *ResultTableViewController;
}
#property(nonatomic, assign) QuestionView *QuestionViewController;
#property(nonatomic, assign) ResultView *ResultViewController;
#property(nonatomic, assign) ResultTableView *ResultTableViewController;
-(void)switchToResultMode:(QuestionPath *)QuestionPath;
-(void)switchToResultTableMode;
-(void)switchBack:(BOOL)Reset;
#end
.m
//
// RootNavigationController.m
// IPhonePPS
//
// Created by Administrateur local on 11-02-11.
// Copyright 2011 Le Groupe CDGI Inc. All rights reserved.
//
#import "RootNavigationController.h"
#implementation RootNavigationController
#synthesize QuestionViewController, ResultViewController, ResultTableViewController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code.
QuestionViewController = [[QuestionView alloc] initWithNibName:NULL bundle:NULL];
ResultViewController = [[ResultView alloc] initWithNibName:NULL bundle:NULL];
ResultTableViewController = [[ResultTableView alloc] initWithNibName:NULL bundle:NULL];
//Set the navigation bar hidden
[self setNavigationBarHidden:YES];
//Push the question view on the stack
[self pushViewController:self.QuestionViewController animated:YES];
}
return self;
}
- (void)dealloc {
[super dealloc];
}
-(void)switchToResultMode:(QuestionPath *)QuestionPath {
[self pushViewController:ResultViewController animated:YES];
[ResultViewController setQuestionPath:QuestionPath];
}
-(void)switchToResultTableMode {
[self pushViewController:ResultTableViewController animated:YES];
}
-(void)switchBack:(BOOL)Reset{
if(Reset){
if([self.viewControllers count] == 3){
[self popToRootViewControllerAnimated:YES];
}else {
[self popViewControllerAnimated:YES];
}
[QuestionViewController resetAnswers];
}else {
[self popViewControllerAnimated:YES];
}
}
//-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
// if([self visibleViewController] == self.ResultTableViewController || toInterfaceOrientation == UIInterfaceOrientationPortrait){
// return YES;
// }else {
// return NO;
// }
//}
- (BOOL) shouldAutorotate {
return YES;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
#end
spent two complete days trying to debug this but I give up and would really appreciate your help with this issue
PR
It would be better to just use [[alloc] init] if you don't have a nib for your navigation controller. Also, your navigation controller should be initialized with its own rootViewcontroller. I don't know which one you want to be first, but it should look something like this:
MyFirstViewControllerClass *rootVC = [MyFirstViewControllerClass alloc] initWithNibName:#"MyFirstViewController" bundle:nil];
RootNavigationController *nav = [[RootNavigationController alloc]initWithRootViewController:rootVC];
self.window.rootViewController = nav;
You're calling [self.window setRootViewController:RootNavigationViewController]; Notice - setRootViewController. It wants a viewController. Your RootNavigationViewController is a NavigationController as referenced here #interface RootNavigationController : UINavigationController not a viewController.
It looks like you should do something like this
RootNavigationViewController = [[RootNavigationController alloc] initWithNibName:NULL bundle:NULL];
[window makeKeyAndVisible];
[window addSubview:RootNavigationViewController.view];
(referenced from Programmatically build / navigate a Navigation Controller)
I'm not sure if using
[self pushViewController:self.QuestionViewController animated:YES];
in the RootNavigationViewController is the same as doing something like this
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
But that should point you in a good direction to debug your issue.
You should init your RootNavigationController with a rootViewController first :
[RootNavigationController initWithRootViewcontroller:QuestionViewController];
You can find this from the UINavigationController reference :
Because the UINavigationController class inherits from the
UIViewController class, navigation controllers have their own view
that is accessible through the view property. When deploying a
navigation interface, you must install this view as the root of
whatever view hierarchy you are creating.
For instance, in -(void)switchBack:(BOOL)Reset; you popToRootViewController without even having set it.
Is there any easy way to manually set the orientation of an interface? I need to set the interface to portrait even though the device orientation might be in landscape during loading. Kinda want to stay away from CGAffineTransforms.
One method I know that works for me (and is a bit of a hack and can display one orientation before changing to the orientation you want) is:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
UIViewController *c = [[UIViewController alloc]init];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
[c release];
}
}
First, set your app and views to only support portrait, then use this category method taken from my refactoring library, es_ios_utils:
#interface UIViewController(ESUtils)
// Forces without using a private api.
-(void)forcePortrait;
#end
#implementation UIViewController(ESUtils)
-(void)forcePortrait
{
//force portrait orientation without private methods.
UIViewController *c = [[UIViewController alloc] init];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
[c release];
}
#end
The view, dismissed before the frame completes, won't be displayed.
override this to control the orientation until loading...
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation