2011-11-08 27 views
13

在SO的其他問題中,有been reported,因此iOS 5會根據此發行說明更改分割視圖控制器的旋轉回調的發送方式。這不是欺騙(我認爲),因爲我找不到SO另一個問題,與如何在iOS 5的調整拆分視圖控制器的使用涉及到應對變化:iOS5打破UISplitViewController旋轉回調,如何手動調用?

旋轉回調iOS 5中不適用於在全屏幕上顯示 的視圖控制器。這意味着,如果您的代碼 在另一個視圖控制器上顯示視圖控制器,然後用戶隨後將設備旋轉到不同的方向,則在解除 時,底層控制器(即呈現控制器)將不會接收到任何旋轉回調。但請注意, 控制器將在 重新顯示時收到viewWillLayoutSubviews呼叫,並且可以從 此方法查詢interfaceOrientation屬性並用於正確佈置控制器。

我在配置我的根分離視圖控制器中的彈出按鈕時出現問題(應該在縱向顯示彈出窗口中的左窗格視圖時)。這裏是我的應用程序的啓動順序如何使用的iOS 4.x中工作時,該設備是在橫向模式:

  1. 安裝拆分視圖控制器到窗口[window addSubview:splitViewController.view]; [window makeKeyAndVisible];。即使設備已處於橫向模式,也會導致在委託上調用splitViewController:willHideViewController:withBarButtonItem:forPopoverController:(即模擬橫向 - >縱向旋轉)。

  2. 呈現全屏模式(我的加載屏幕),它完全覆蓋下面的分割視圖。

  3. 完成加載並關閉加載屏幕模態。由於設備處於橫向模式,因爲顯示分割視圖控制器時,會導致在代表上調用splitViewController:willShowViewController:invalidatingBarButtonItem:(即模擬人像 - >風景旋轉),從而使條形按鈕項目失效,將其從右側移除的分裂觀點,並把我們留在我們想要的地方。萬歲!

所以,問題是,由於在發行說明中描述的變化,無論在的iOS 4.3導致splitViewController:willShowViewController:invalidatingBarButtonItem:被稱爲iOS版5.不再發生了,我試着子類UISplitViewController,所以我可以提供內部發生的如發行說明中所建議的viewWillLayoutSubviews的自定義實現,但我不知道如何重現iOS 4觸發的所需內部事件序列。我試過這個:

- (void) viewWillLayoutSubviews 
{ 
    [super viewWillLayoutSubviews]; 

    UINavigationController *rightStack = [[self viewControllers] objectAtIndex:1]; 
    UIViewController *rightRoot = [[rightStack viewControllers] objectAtIndex:0]; 
    BOOL rightRootHasButton = ... // determine if bar button item for portrait mode is there 

    // iOS 4 never goes inside this 'if' branch 
    if (UIInterfaceOrientationIsLandscape([self interfaceOrientation]) && 
     rightRootHasButton) 
    { 
     // Manually invoke the delegate method to hide the popover bar button item 
     [self.delegate splitViewController:self 
        willShowViewController:[[self viewControllers] objectAtIndex:0] 
       invalidatingBarButtonItem:rightRoot.navigationItem.leftBarButtonItem]; 
    } 
} 

這主要是工作,但不是100%。問題是你自己調用委託方法實際上並不是使條形按鈕項無效,所以當你第一次旋轉到肖像時,系統認爲條形按鈕項仍然正確安裝,並且不會嘗試重新安裝它。只有當你再次旋轉到橫向,然後回到縱向後,系統纔會回到正確的狀態,並且實際上將以縱向模式安裝彈出欄按鈕項目。

基於this question,我還試着手動調用所有的回調回調,而不是觸發委託方法,例如,:

// iOS 4 never goes inside this 'if' branch 
if (UIInterfaceOrientationIsLandscape([self interfaceOrientation]) && 
    rightRootHasButton) 
{ 
    [self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0]; 
    [self willAnimateRotationToInterfaceOrientation:self.interfaceOrientation duration:0]; 
    [self didRotateFromInterfaceOrientation:self.interfaceOrientation]; 
} 

然而,這似乎只是導致無限循環回viewWillLayoutSubviews :(

有誰知道什麼模擬的iOS4,風格輪事件的正確方法是,從出現拆分視圖控制器在全屏幕模式背後?或者你不應該模擬它們嗎?是否有另一種最佳實踐方法已經成爲iOS5的標準?

任何幫助真的很感謝,因爲這個問題阻礙了我們提交我們的iOS5 bug修正版發佈到App Store。

回答

11

我不知道處理這種情況的正確方法。但是,以下似乎在iOS的5

  1. 要爲我工作在splitViewController:willHideViewController:withBarButtonItem:forPopoverController:,存儲在類似self.barButtonItem到barButtonItem參考。將用於顯示按鈕的代碼移入單獨的方法,例如ShowRootPopoverButtonItem

  2. splitViewController:willShowViewController:invalidatingBarButtonItem:中,清除self.barButtonItem的引用。將用於顯示按鈕的代碼移動到單獨的方法中,例如InvalidateRootPopoverButtonItem

  3. viewWillLayoutSubviews,手動顯示或隱藏按鍵,根據不同的接口方向

這是我實現viewWillLayoutSubviews。請注意,致電self.interfaceOrientation總是會返回肖像,因此我使用statusBarOrientation

- (void)viewWillLayoutSubviews 
{ 
    if (UIInterfaceOrientationIsPortrait(
     [UIApplication sharedApplication].statusBarOrientation)) 
    { 
     [self ShowRootPopoverButtonItem:self.barButtonItem]; 
    } 
    else 
    { 
     [self InvalidateRootPopoverButtonItem:self.barButtonItem]; 
    } 
} 
+1

嘿諾亞 - 感謝您的解決方案 - 它也適用於我。這有點不幸,因爲viewWillLayoutSubviews比循環事件更經常被調用,因此填充所有按鈕隱藏/顯示邏輯意味着它會更頻繁地運行,但是看起來這是iOS5-ish的方式這東西現在。 – glenc