2015-05-07 92 views
3

我正在使用此观察者:UIDeviceOrientationDidChangeNotification来检测用户何时更改设备方向。当方向改变为风景时,我提出一个新的UIViewController或在他将其更改回肖像时关闭此UIViewController。当用户开始旋转的时间和快速的设备数量UIViewController动画等到动画完成

我的问题开始,然后应用程序都疯了,直到我得到这个错误:

Warning: Attempt to present on whose view is not in the window hierarchy!`.

什么是最好的方式等到动画结束,然后改变旋转?

这是我使用的是什么样的呈现视图控制器

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

你为什么要设置[UIDevice orientation]?它是什么样的可怕的黑客? – Sulthan

+0

嗯,它实际上工作得很好,为什么要破解?我应该用什么来代替? –

+0

'[UIDevice orientation]'只读是有原因的。黑客是你正在使用反射('setValue:')访问它,绕过'readonly'状态。如果您不想使用控制器的默认旋转支持,则可以在呈现的控制器视图中使用'transform'。 – Sulthan

回答

2

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

这是通过添加以下代码当动画开始做:

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

,并完成处理:

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

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

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; 

查看您是否应该启动另一个动画。