iOS switching view controllers, afhankelijk van de richting van het apparaat

Ik ontwikkel een Augmented Reality-applicatie, alles werkte tot nu toe dat ik twee verschillende soorten visualisatie nodig heb (AR en kaart), afhankelijk van de richting van het apparaat. In het bijzonder zou de applicatie landscapeControlController moeten gebruiken wanneer het apparaat in landscape-modus is terwijl het een andere controller zou moeten gebruiken (genaamd faceUpViewController) wanneer de oriëntatie van het apparaat "face-up" is. Ik probeerde het met twee eenvoudige view controllers en het werkt prima. Het probleem doet zich voor wanneer de landscapeViewController de AR-controller gebruikt. Het uitzicht is helemaal wit en ik begrijp niet waarom. Beide controllers worden "ingesloten" door een rootview-controller. Ik doe alles door zo te coderen zonder nib-bestanden. Hier is de code:

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 Very simple version

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

Ik zeg opnieuw dat ik alles doe door er zonder nib-bestanden mee te coderen. Ik stel elk advies zeer op prijs! Bedankt

1

2 antwoord

Het belangrijkste probleem met het toevoegen en verwijderen van de weergaven van uw 'kind'-beeldregelaars zoals u hier heeft gedaan, is dat de levenscyclusmethoden van de weergavecontroller ( viewWillAppear: , viewDidAppear: , enz.) zal nooit worden aangeroepen op uw child view-controllers. Containers zoals UINavigationController en UITabBarController hebben altijd geweten hoe methoden zoals deze naar hun kinderen moeten worden gedelegeerd, maar UIViewController heeft officieel niet de mogelijkheid om nestzichtcontrollers onder uw eigen aangepaste container vóór iOS 5. Het was mogelijk, maar er was veel meer werk voor nodig om het goed te doen.

Als u de aanpak van het toevoegen en verwijderen van subweergaven wilt behouden, hebt u twee opties:

  1. Vereist iOS 5+ en bel addChildViewController: , removeFromParentViewController , transitionFromViewController: toViewController: duur: options: animaties: voltooiing: , willMoveToParentViewController: , en didMoveToParentViewController: zoals beschreven in de Een containerviewcontroller implementeren van de UIViewController klassenreferentie.

  2. Om oudere iOS-versies te ondersteunen, moet u veel van de methoden van de klasse UIViewController overschrijven en die oproepen handmatig delegeren aan uw child view-controllers om ze te laten werken zoals verwacht. Ik zou bijzondere aandacht besteden aan de secties getiteld "Reageren op weergave-evenementen" en "Reageren op rotatie-evenementen bekijken" in de UIViewController klassenreferentie.

Een andere aanpak voor pre-iOS 5-ondersteuning is om uw child view-controllers te presenteren met behulp van presentModalViewController: animated: in plaats van hun weergaven toe te voegen als subweergaven aan een container. Apple beschrijft deze aanpak in de Programmeerhandleiding voor View Controller voor iOS onder de sectie Een alternatieve liggende interface maken . Het voordeel van deze aanpak is dat uw child view-controllers officieel worden ondersteund als eersteklas leden van de view controller-hiërarchie, dus zal UIKit hun levenscycli automatisch beheren. U hoeft niet al deze methoden handmatig te negeren en te delegeren.

4
toegevoegd
Ok dus het probleem met mijn code is dat ik een normale UIViewController gebruik en geen UINavigationController of UITabViewController en ( viewWillAppear: en viewDidAppear: ) nooit zal worden aangeroepen. Maar alleen om te begrijpen waarom als ik dezelfde weergave van faceUpViewController initialiseer, maar een andere bgcolor in het landschapViewController verandert, zodra ik de richting van het apparaat wijzig? Aangezien ik de oudere versie van iOS moet ondersteunen en ik wil de bovengenoemde methoden niet opheffen, zal ik de laatste optie gebruiken die je mij hebt beschreven. Ik zal het proberen, kun je ook proberen of het werkt als je tijd hebt?
toegevoegd de auteur ubiAle, de bron

Misschien wilt u proberen uw acceptatiegraad een beetje te verhogen - meer mensen zouden u willen helpen.

Hoe dan ook, wilde gok: probeer in je root-controller de inhoud van

  deviceOrientationDidChange

in

  deviceOrientationWillChange.
1
toegevoegd
Mijn fout. Meestal plaats ik dit type code in de UIViewController-methoden met de naam: willRotateToInterfaceOrientation en didRotateFromInterfaceOrientation. Ik heb je methode van naderbij bekeken en je verwerkt slechts 2 van de 6 mogelijke richtingen - misschien is dat opzettelijk. U kunt ook proberen de recursiveDescription in de foutopsporing om te zien wat er eigenlijk in de root-weergave: developer.apple.com/library/ios/#technotes/tn2239/_index.htm‌ l
toegevoegd de auteur Rayfleck, de bron
hoe dan ook, wat bedoel je met het gebruik van deviceOrientationWillChange? deviceOrientationDidChange is de aangepaste methode die wordt gemeld wanneer het apparaat de richting verandert!
toegevoegd de auteur ubiAle, de bron