iOS переключает контроллеры вида в зависимости от ориентации устройства - PullRequest
1 голос
/ 07 декабря 2011

Я занимаюсь разработкой приложения дополненной реальности, до сих пор все работало правильно, поэтому мне нужны два разных вида визуализации (AR и Map) в зависимости от ориентации устройства.В частности, приложение должно использовать landscapeViewController, когда устройство находится в ландшафтном режиме, в то время как оно должно использовать другой контроллер (с именем faceUpViewController), когда ориентация устройства «вверх».Я попытался сделать это с двумя простыми контроллерами представления, и это прекрасно работает.Проблема возникает, когда landscapeViewController использует контроллер AR.Вид полностью белый, и я не понимаю, почему.Оба этих контроллера «содержатся» в контроллере Root View.Я делаю все, кодируя так без файлов пера.Вот код:

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

Я еще раз говорю, что все делаю, кодируя их, тем самым, без перафайлы.Я очень ценю любые советы!Спасибо

Ответы [ 2 ]

4 голосов
/ 07 декабря 2011

Основная проблема с добавлением и удалением «дочерних» представлений контроллеров представления, как вы сделали здесь, заключается в том, что методы жизненного цикла контроллера представления (viewWillAppear:, viewDidAppear: и т. Д.) Никогда не будут вызываться на вашем ребенке вид контроллеров. Контейнеры, такие как UINavigationController и UITabBarController, всегда знали, как делегировать подобные методы соответствующим образом своим дочерним элементам, но UIViewController официально не поддерживала возможность вложения контроллеров представления в ваш собственный контейнер до iOS 5. Это было возможно , но потребовалось гораздо больше работы, чтобы сделать это правильно.

Если вы хотите придерживаться подхода добавления и удаления подпредставлений, у вас есть два варианта:

  1. Требуется iOS 5+, и звоните addChildViewController:, removeFromParentViewController, transitionFromViewController:toViewController:duration:options:animations:completion:, willMoveToParentViewController: и didMoveToParentViewController: как описано в разделе Реализация контроллера представления контейнера Справочника по классам UIViewController.

  2. Чтобы поддерживать более старые версии iOS, вам придется переопределить многие методы класса UIViewController и делегировать эти вызовы вручную вашим дочерним контроллерам представления, чтобы они вели себя так, как ожидалось. Я бы уделил особое внимание разделам «Ответ на события просмотра» и «Ответ на события вращения просмотра» в справочнике по классам UIViewController.

Другой подход к поддержке до iOS 5 состоит в том, чтобы представить ваши дочерние контроллеры представления, используя presentModalViewController:animated:, а не добавлять их представления в качестве подпредставлений в контейнер. Apple описывает этот подход в Руководстве по программированию View Controller для iOS в разделе Создание альтернативного ландшафтного интерфейса . Преимущество этого подхода состоит в том, что ваши дочерние контроллеры представления официально поддерживаются в качестве первоклассных членов иерархии контроллеров представления, поэтому UIKit автоматически будет соответствующим образом управлять своими жизненными циклами. Вам не придется переопределять и делегировать все эти методы вручную.

1 голос
/ 07 декабря 2011

Возможно, вы захотите немного повысить свой показатель приемлемости - больше людей захотят вам помочь.

В любом случае, дикая догадка: в вашем корневом контроллере попробуйте поместить содержимое

  deviceOrientationDidChange

в

  deviceOrientationWillChange.
...