IPhone - work with orientation and several views

I searched long and hard, trying to figure it out. It took about 4-5 hours before I finally managed to find a solution. I will answer my question in order to support those who come to the same problem.

So, I created the Critical Mass Typer application. This is a typed game that uses the keyboard as the main control method. Words move to the center of the screen where you have a core. You enter a word and delete the word before it reaches your core. If 4 words fall into your core, you reach a critical mass and explode (the game ends).

Now I wanted to be able to support both landscape and portrait modes in the game. I thought about it ahead of time and developed my classes so that they were easy to implement. Setting up the game for this was not a problem. Correctly rotate the submission was.

One thing that came up pretty quickly is any view that returns NO for the view controller's toAutorotateToInterfaceOrientation method will cancel the return of its subzones.

So, my main view controller (CriticalMassViewController) controls the launch / menu of the game and adds a view controller that starts game mode (CMGameViewController) as a subordinate. I want my main view manager to be in landscape mode, because if I rotate it, the animation / buttons all run sideways. I would need to create another view or change the position of everything on the screen if I wanted it to be configured for portrait mode. However, my game play should be able to switch. To accomplish this, you set the return value to the specific mode in which you want your main view to be. Then tell the game mind not to return any mode. After that, register the game presentation for notifications, then process the rotation yourself.

For example: CriticalMassViewController.m:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationLandscapeRight); } 

CMGameViewController.m

 - (void)viewDidLoad { [super viewDidLoad]; /*GUI setup code was here*/ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil]; } -(void)didRotate:(NSNotification *)nsn_notification { UIInterfaceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation]; /*Rotation Code if(interfaceOrientation == UIInterfaceOrientationPortrait) { //Portrait setup } else if(interfaceOrientation == UIInterfaceOrientationLandscapeRight) { //Landscape setup } */ } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return NO; } 

OK, so what's going on here? My main view controller only wants to be in LandscapeRight mode. Thus, it remains so, as it is never registered for any other orientation for automatic rotation. My game view controller should be able to rotate. If I use the following code for shouldAutorotateToInterfaceOrientation

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeRight); } 

IT DOES NOT ROTATE WHEN IT HAS A CHANGE IN ORIENTATION. This is because his superview says he doesn't want to spin. As soon as the superview returns no, subview is not even asked. Therefore, instead, we, the controller of the game presentation, simply say “No,” I do not want to autorotate into any representation. Then we register a notification of a change in orientation and call our own rotation method.

These last bits of code are how you handle the rotation yourself. Call rotateView from inside didRotate. Please note: I want the user to be able to rotate after choosing the difficulty, so I have the logic inside the didRotate method to determine whether to even rotate. Comments in the code will explain why certain things happen.

 -(void) rotateView:(UIInterfaceOrientation)uiio_orientation { /*This line is very important if you are using the keyboard. This was actually the largest problem I had during this entire ordeal. If you switch orientations while the keyboard is already being displayed, it will stay in landscape orientation. To get it to switch to portrait, we have to tell the status bar that its orientation has changed. Once you do this, the keyboard switches to portrait*/ [UIApplication sharedApplication].statusBarOrientation = uiio_orientation; //Get the view you need to rotate UIView *portraitImageView = self.view; /*Check to make sure that you are in an orientation that you want to adjust to. If you don't check, you can make your view accidently rotate when the user orientates their phone to a position you aren't expecting*/ if(uiio_orientation == UIInterfaceOrientationPortrait || uiio_orientation == UIInterfaceOrientationLandscapeRight) { if(uiio_orientation == UIInterfaceOrientationPortrait) { //This transform rotates the view 90 degrees counter clock wise. portraitImageView.transform = CGAffineTransformMakeRotation(-M_PI/2); } else if(uiio_orientation == UIInterfaceOrientationLandscapeRight) { //This transform rotates the view back to its original position portraitImageView.transform = CGAffineTransformMakeRotation(0); } CGRect frame = portraitImageView.frame; frame.origin.y = 0; frame.origin.x = 0; frame.size.width = portraitImageView.frame.size.height; frame.size.height = portraitImageView.frame.size.width; portraitImageView.frame = frame; } } 

Hope this helps someone, I know that I had a very difficult time, especially the keyboard, going from landscape to portrait.

+4
source share
2 answers

Custom UIViewControllers should not be inserted in one screen. I believe the Apple line is "one UIViewController per screen." Orientation problems like this are one of the main reasons. This is a clear “mistake”, one of which I am tempted to make in some cases: the temptation is to use the UIViewController as the UIView loader in this case. There is no real reason to use the UIViewController in general as a nested or reusable widget component on the screen, just to get its presentation, you really do not get any benefit, because all these useful convenient functions, such as changing the orientation, viewWillAppear, viewWillDisappear, will not invoked automatically for you by any other UIViewController except your own! These calls are not "transferred" but "redirected" from the parent of the UIViewController to the child of the UIViewController. And if you write your own subclass of UIViewController, you are responsible for passing any of these inherited method calls.

Your internal UIViewController was not “not called” because the external UIViewController answered NO, it was not called because you did not redirect the call to your nested UIViewController yourself. The orientation change method shouldAutorotateToInterfaceOrientation , like other viewWill * methods, is not passed to all UIViewControllers, they are passed hierarchically from the top-level window, from class to class. Built-in UIViewControllers, such as UINavigationControllers and UITabBarControllers, explicitly pass these calls on to their children, so it seems like they are translated as they arrive, but when you insert your own UINavigationController subclass into the VC hierarchy, you must pass these calls on to any UINavigationControllers children yourself. This is what you have to do if you want to write your own "global VC controller", for example, replacing the UITabBarController.

+2
source
  if([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait || [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown) { //for portrait NSLog(@"portrait"); } else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft || [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight) { // code for landscape orientation NSLog(@"landscape"); } 
0
source

Source: https://habr.com/ru/post/1314585/


All Articles