繁体   English   中英

iOS根据设备方向切换视图控制器

[英]iOS switching view controllers depending on the device orientation

我正在开发一个增强现实应用程序,到目前为止一切正常,根据设备的方向,我需要两种不同类型的可视化(AR和Map)。 特别是当设备处于横向模式时,应用程序应使用landscapeViewController,而当设备的方向为“面朝上”时,应用程序应使用另一个控制器(名为faceUpViewController)。 我试着用两个简单的视图控制器来做,并且工作正常。 当landscapeViewController使用AR控制器时,会发生问题。 视图是完全白色的,我不明白为什么。 这两个控制器均由“根视图控制器”“包含”。 我通过编码来完成所有工作,因此没有nib文件。 这是代码:

RootViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}

- (void)deviceOrientationDidChange:(NSNotification *)notification{

    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

    if (orientation == UIDeviceOrientationLandscapeLeft) {
        if (self.landscapeViewController.view.superview == nil) {
            if (self.landscapeViewController == nil) {
                LandscapeViewController *lvc = [[LandscapeViewController alloc] init];
                self.landscapeViewController = lvc;
                [lvc release];
            }
            [self.faceUpViewController.view removeFromSuperview];
            [self.view addSubview:self.landscapeViewController.view];
        }
    }

    if (orientation == UIDeviceOrientationFaceUp) {
        if (self.faceUpViewController.view.superview == nil) {
            if (self.faceUpViewController == nil) {
                FaceUpViewController *fvc = [[FaceUpViewController alloc] init];
                self.faceUpViewController = fvc;
                [fvc release];
            }
            [self.landscapeViewController.view removeFromSuperview];
            [self.view addSubview:self.faceUpViewController.view];
        }
    }

}

@end

LandscapeViewController.m

// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
    UIView *landscapeView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
    landscapeView.backgroundColor = [UIColor yellowColor];
    self.view = landscapeView;
    [landscapeView release];

    ARController *arC = [[ARController alloc] initWithViewController:self];
    arC.landscapeViewController = self;
    self.arController = arC;
    [arC release];
}

//When the view appear present the camera feed
- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 
    [_arController presentModalARControllerAnimated:NO];
}

FaceUpViewController.m

- (void)loadView
{
    UIView *faceUpView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
    faceUpView.backgroundColor = [UIColor blueColor];
    self.view = faceUpView;
    [faceUpView release];
}

ARController.m非常简单的版本

- (id) initWithViewController:(UIViewController *)theView{

    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {

        self.rootController = theView; 

        //Retrieve screen bounds
        CGRect screenBounds = [[UIScreen mainScreen] bounds]; 

        UIView *overlaidView = [[UIView alloc] initWithFrame: screenBounds];
        self.overlayView =  overlaidView;
        [overlaidView release];
        self.rootController.view = overlayView;

        // Initialise the UIImagePickerController 
        UIImagePickerController *picker= [[UIImagePickerController alloc] init];
        self.pickerController = picker;
        [picker release];

        self.pickerController.sourceType = UIImagePickerControllerSourceTypeCamera; 
        self.pickerController.cameraViewTransform = CGAffineTransformScale(
                                                                           self.pickerController.cameraViewTransform, 1.0f, 1.12412f);

        self.pickerController.showsCameraControls = NO; 
        self.pickerController.navigationBarHidden = YES; 
        self.pickerController.cameraOverlayView = _overlayView;
    }

    return self;
}

- (void)presentModalARControllerAnimated:(BOOL)animated{
    [self.rootController presentModalViewController:[self pickerController] animated:animated]; 
    self.overlayView.frame = self.pickerController.view.bounds;
}

@end

我再说一次,我正在通过没有nib文件的编码来做所有事情。 我真的很感谢任何建议! 谢谢

像这里所做的那样,添加和删除“子”视图控制器的视图的主要问题是视图控制器生命周期方法( viewWillAppear:viewDidAppear:等)永远不会在子视图控制器上调用。 诸如UINavigationControllerUITabBarController类的容器一直都知道如何将此类方法适当地委派给他们的孩子,但是UIViewController并没有正式支持在iOS 5之前将视图控制器嵌套在您自己的自定义容器中的功能。这是可能的,但是这花费了很多做正确的更多工作。

如果要坚持添加和删除子视图的方法,则有两个选择:

  1. 需要iOS 5以上版本,并按照UIViewController类参考的“ 实现容器视图控制器”部分中的描述,调用addChildViewController:removeFromParentViewControllertransitionFromViewController:toViewController:duration:options:animations:completion:willMoveToParentViewController:didMoveToParentViewController:

  2. 为了支持较旧的iOS版本,您必须重写UIViewController类的许多方法,并将这些调用手动委派给子视图控制器,以使它们的行为符合预期。 我将特别注意UIViewController类参考中标题为“响应视图事件”和“响应视图旋转事件”的部分。

支持iOS 5之前版本的另一种方法是使用presentModalViewController:animated:显示子视图控制器,而不是将其视图作为子视图添加到容器中。 Apple在《适用于iOS的View Controller编程指南》下的创建备用横向界面一节中介绍了这种方法。 这种方法的优点是,您的子视图控制器作为视图控制器层次结构的一等成员而得到正式支持,因此UIKit将自动适当地管理其生命周期。 您不必手动覆盖和委派所有这些方法。

您可能希望尝试提高接受率-更多的人愿意帮助您。

无论如何,大胆的猜测:在您的根控制器中,尝试将

  deviceOrientationDidChange

进入

  deviceOrientationWillChange.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM