Search code examples
iosmodalviewcontrolleraugmented-reality

Modal view controller not presented anymore after being presented 2/3 times


Here is the thing, I have to integrate an augmented reality functionality into an app. After testing it aside, now I'm ready to integrate it. The app always runs in Portrait, I decided to show the augmented reality when rotating the iPhone in Landscape Right or Left (and of course, if I go back in Portrait the original view controller is shown). In fact the augmented reality is presented modally.

I've got viewController calling ARViewController (modally). It works fine if I rotate like 2 or 3 times, but then this ARViewController is not called anymore, but the app is still running, no crash, no freeze. This ARViewController is initialised with ARController, a class computing all needed for the augmented reality. If I call this ARViewcontroller without the ARController, switching between the view controllers works very fine, a blank window will be called but at least I can rotate the device as much as I want. So, this must come from the ARController, I documented myself on memory leaks (by the way I'm using ARC), I think this could be the reason to the issue since I'm using this ARController many times.

But before going further, I'd like to know if I'm doing anything wrong that could influence the ARController by switching between view controllers:

Here is how I call the ARViewController in viewController:

if (orientation == UIDeviceOrientationLandscapeLeft) {
        NSLog(@"ViewController Landscape left");
        ARViewController *arVC = [[ARViewController alloc] initWithNibName:@"ARViewController" bundle:nil];
        [self setCameraViewController:arVC];
        [arVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal];
        [[self navigationController] presentModalViewController:cameraViewController animated:YES];
        arVC = nil;
    }
    else if (orientation == UIDeviceOrientationLandscapeRight) {
        NSLog(@"ViewController Landscape Right");
        ARViewController *arVC = [[ARViewController alloc] initWithNibName:@"ARViewController" bundle:nil];
        [self setCameraViewController:arVC];
        [arVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal];
        [[self navigationController] presentModalViewController:cameraViewController animated:YES];
        arVC = nil;
    }

the initialisation of ARViewController:

- (void)viewDidLoad {
[super viewDidLoad];
self.arController = [[ARController alloc] initWithViewController:self];
arController.filterDiscover = filterDiscover;
arController.filterEat = filterEat;
arController.filterSleep = filterSleep;

// Listen for changes in device orientation
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

//if ViewController presents this modal ARViewController
if(!arController.filterDiscover && !arController.filterEat && !arController.filterSleep)
    [arController callAlertViewToFilter];
else
    [arController loadData];
}

And finally here is how I go back to the original view controller if I rotate to Portrait in ARViewController:

if (orientation == UIDeviceOrientationPortrait){
    NSLog(@"ARViewController Portrait");
    [self setArController:nil];
    [[super presentingViewController] dismissModalViewControllerAnimated:YES];
}

I tried to be as clear as possible, if anyone has ever had an issue similar to this, it could be great have some clues to solve this. I could have shown the code of the ARController but it is a little too long, for now I'd just like to know if there is anything wrong here. If needed I'll show it.

This might help, I found this output in the debug area when the ARViewController is not being displayed anymore:

2012-10-24 17:57:51.072 beiceland[20348:907] ViewController Landscape Right
2012-10-24 17:57:51.073 beiceland[20348:907] Warning: Attempt to present <ARViewController: 0x203f0c60> on <RevealController: 0x1cd5dca0> while a presentation is in progress!

Solution

  • My bad I was way out of the solution here.

    I used the debugger and breakpoints and repeated the critical sequence, I found out I was not entering:

    - (void)deviceOrientationDidChange:(NSNotification *)notification
    

    anymore. So this is the first time I see such things, the listener for device orientation changes suddenly stops firing. Consequently my solution is quite brutal but at least it has the merit of stopping the issue, just after detecting the device orientation change I stop the listener:

    if (orientation == UIDeviceOrientationLandscapeLeft) {
            NSLog(@"ViewController Landscape left");
            [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
            [[NSNotificationCenter defaultCenter] removeObserver:self];
            ARViewController *arVC = [[ARViewController alloc] initWithNibName:@"ARViewController" bundle:nil];
            [self setCameraViewController:arVC];
            arVC = nil;
            [cameraViewController setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal];
            [[super navigationController] presentModalViewController:cameraViewController animated:YES];
    }
    

    And each time I'm using the viewController (the calling view controller), I reinitialize the listener, it means in viewDidAppear:

    // Listen for changes in device orientation
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object:nil];
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    

    Well now it's solved but I have to admit I'm disappointed of finding such kind of solution.