2015-05-07 138 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]; 

查看您是否應該啓動另一個動畫。