iPhone-使用方向和多视图

iPhone-使用方向和多视图,iphone,ipad,ipod-touch,Iphone,Ipad,Ipod Touch,我花了很长时间和精力去寻找答案。我花了大约4-5个小时才最终找到解决方案。我将回答我自己的问题,努力为任何遇到同样问题的人提供支持 因此,我创建了应用程序临界质量打字机。这是一款以键盘为主要控制手段的打字游戏。文字移动到屏幕的中心,在那里你有一个核心。你输入这个单词,在它到达你的核心之前把它吹走。如果4个单词到达你的核心,你达到临界质量,然后爆炸(游戏结束) 现在,我想在游戏中同时支持横向和纵向模式。我提前考虑了它,并设计了易于实现的类。设置游戏这样做不是问题。使视图正确旋转是非常困难的 很快出

我花了很长时间和精力去寻找答案。我花了大约4-5个小时才最终找到解决方案。我将回答我自己的问题,努力为任何遇到同样问题的人提供支持

因此,我创建了应用程序临界质量打字机。这是一款以键盘为主要控制手段的打字游戏。文字移动到屏幕的中心,在那里你有一个核心。你输入这个单词,在它到达你的核心之前把它吹走。如果4个单词到达你的核心,你达到临界质量,然后爆炸(游戏结束)

现在,我想在游戏中同时支持横向和纵向模式。我提前考虑了它,并设计了易于实现的类。设置游戏这样做不是问题。使视图正确旋转是非常困难的

很快出现的一件事是:对于视图控制器的shouldAutorotateToInterfaceOrientation方法,任何返回NO的视图都将抵消其子视图的返回

因此,我的主视图控制器(CriticalMassViewController)控制游戏的启动/菜单,并作为子视图添加运行游戏模式的视图控制器(CMGameViewController)。我只希望我的主视图控制器处于横向模式,因为如果我旋转它,动画/按钮都会从侧面运行。如果我想将其设置为纵向模式,我必须创建另一个视图或更改屏幕上所有内容的位置。但是,我的游戏视图需要能够切换。要完成此操作,请将返回值设置为希望主视图处于的特定模式。然后告诉你的游戏视图不要返回任何模式。之后,注册游戏视图以获取通知,然后自行处理轮换

例如: 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; 
    }
好吧,这里发生了什么?我的主视图控制器只希望处于LandscapeRight模式。所以它保持不变,因为它从不注册任何其他方向来自动旋转。我的游戏视图控制器需要能够旋转。如果我对shouldAutorotateToInterfaceOrientation使用以下代码

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
        return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
    }
当IPHONE改变方向时,它不会旋转。这是因为它的超级视图显示它不想旋转。一旦超级视图返回no,子视图甚至不会被询问。因此,我们的游戏视图控制器只是说不,我不想自动旋转到任何视图。然后我们注册一个方向改变的通知,并调用我们自己的rotate方法

这些代码的最后几位是您自己处理旋转的方式。从内部调用rotateView。注意,我只希望用户在选择难度后能够旋转,因此我在didRotate方法中有逻辑来确定它是否应该旋转。代码中的注释将解释某些事情发生的原因

-(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;
    }
}

我希望这能帮助一些人,我知道我在这方面经历了一段非常艰难的时光,尤其是键盘从横向到纵向的变化

用户编写的UIViewController不应嵌套在单个屏幕上。我相信苹果的产品线是“每个屏幕一个UIViewController”。像这样的方向改变问题是一个重要原因。这是一个可以理解的“错误”,在某些情况下我很想犯这样的错误:在本例中,诱惑是使用UIViewController作为UIView加载程序。根本没有真正的理由将UIViewController用作屏幕中的嵌套或可重用“小部件”组件,只是为了查看它,实际上没有任何好处,因为所有这些有用的便捷功能,如方向更改、视图将出现、视图将消失,不会由除您自己的UIViewController之外的任何其他UIViewController自动为您调用!这些调用不是“广播”,而是从UIViewController父级“转发”到UIViewController子级。如果您编写自己的UIViewController子类,您将负责传递任何这些继承的方法调用


您的内部UIViewController未被“调用”,因为外部UIViewController回答“否”,而未被调用,因为您自己没有将调用转发给嵌套的UIViewController。方向更改方法
应自动旋转指针FaceOrientation
,与其他viewWill*方法一样,不会广播到所有UIViewController,而是从顶级窗口向下传递,从一个类传递到另一个类。内置的UIViewController(如UINavigationController和UIAbbarController)会显式地将这些调用传递给它们的子对象,这就是为什么它们到达时看起来像是广播,但当您将自己的UINavigationController子类插入VC层次结构时,您必须自己将这些调用传递给任何子UINavigationController。如果你想编写自己的“全局控制器VC”,比如UITabBarController的替代品,这就是你必须做的。

这条评论与方向无关,但我看着你的应用程序,就像你在“让我们做这个!”这个短语中使用的字体一样。那是什么字体?字体叫做“刀片2”(我想是受电影启发的)。“每个屏幕一个UIViewController”实际上从未被提及。你所说的是“每个视图一个ViewController”,意思是视图控制器和它们控制的视图之间有一对一的关系是个好主意,这只是程序员常用的约定。除此之外,这不是“规则”而是用来让事情“更容易”的指南。此外,视图控制器会自动将消息传递给其子视图控制器。如果您将所有shouldAutorotateToInterfaceOrientation方法设置为返回YES,则它们都会旋转您所说的层次结构为…/customVC-a/customVC-B,customVC-B将自动调用其方向方法,而无需转发它们
 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");
        }