Waiting for UIViewController animation before animation completes

I use this observer: UIDeviceOrientationDidChangeNotification

to detect when the user changes device orientation. When the orientation has changed to a landscape, I present a new one UIViewController

or reject this UIViewController

one when it changes to a portrait.

My problem starts when the user starts to rotate the number of devices times and quickly and then the app goes crazy until I get this error:

Warning. Try to imagine whose view is not in the window hierarchy! `.

What's the best way to wait for the animation to finish and then change the rotation?

This is what I am using in the view of the view controller :

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self beginDeviceOrientationListener];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)beginDeviceOrientationListener
{
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];
}

- (void)orientationChanged:(NSNotification *)notification
{
    UIDevice *device = notification.object;
    switch (device.orientation)
    {
        case UIDeviceOrientationLandscapeLeft:
        case UIDeviceOrientationLandscapeRight:
        {
            TheViewControllerToPresent *viewController = [[TheViewControllerToPresent alloc] init];
            [self presentViewController:viewController animated:YES completion:nil];
            [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationLandscapeRight] forKey:@"orientation"];
            [[UIApplication sharedApplication] setStatusBarOrientation:[[[UIDevice currentDevice] valueForKey:@"orientation"] integerValue] animated:YES];
            [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
        }
            break;

        default:
            break;
    }
}

      

This is what I am using in the Presented View Controller :

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self beginDeviceOrientationListener];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)beginDeviceOrientationListener
{
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];
}

- (void)orientationChanged:(NSNotification *)notification
{
    UIDevice *device = notification.object;
    switch (device.orientation)
    {
        case UIDeviceOrientationPortrait:
        {
            [self dismissViewControllerAnimated:YES completion:nil];
            [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationPortrait] forKey:@"orientation"];
            [[UIApplication sharedApplication] setStatusBarOrientation:[[[UIDevice currentDevice] valueForKey:@"orientation"] integerValue] animated:YES];
        }
            break;
        default:
            break;
    }
}

      

+3


source to share


1 answer


The simplest solution I use myself is to stop the user from making any changes during animation.

This is done by adding the following code when the animation starts:

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];

      

and the completion handler:



[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];

      

The user can rotate the device, but no events will be generated during animation, so animations will not collide. However, when the animation ends, you must explicitly check the orientation:

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

      

to see if another animation should run or not.

+2


source







All Articles