【问题标题】:UIViewController animations wait until animation completeUIViewController 动画等到动画完成
【发布时间】:2015-07-17 19:48:24
【问题描述】:

我正在使用这个观察者:UIDeviceOrientationDidChangeNotification 来检测用户何时更改设备方向。当方向更改为横向时,我会呈现一个新的UIViewController,或者当他将其更改回纵向时将其关闭。

当用户开始快速旋转设备数次时,我的问题就开始了,然后应用程序变得疯狂,直到我收到此错误:

警告:尝试展示不在窗口层次结构中的视图!`。

等到动画结束然后更改旋转的最佳方法是什么?

这是我在 Prepresenting 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;
    }
}

这就是我在呈现的视图控制器上使用的:

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

【问题讨论】:

  • 你为什么要设置[UIDevice orientation]?这是什么可怕的黑客行为?
  • 嗯,它实际上工作得很好,为什么要破解?我应该改用什么?
  • [UIDevice orientation] 是只读的,这是有原因的。 hack 是您正在使用反射 (setValue:) 访问它,绕过 readonly 状态。如果您不想使用控制器具有的默认旋转支持,您可以在呈现的控制器的视图上使用transform

标签: ios objective-c uiviewcontroller uideviceorientation


【解决方案1】:

我自己使用的最简单的解决方案是在动画正在进行时阻止用户进行任何更改。

这是通过在动画开始时添加以下代码来完成的:

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

到完成处理程序:

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

用户可以旋转设备,但在动画期间不会生成事件,因此动画不会发生碰撞。但是,当动画结束时,您应该明确检查方向:

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

看看你是否应该开始另一个动画。

【讨论】:

    猜你喜欢
    • 2013-01-21
    • 2011-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 2012-08-23
    相关资源
    最近更新 更多