2011-11-08 14 views
13

Podobnie jak been reported w innych pytaniach tutaj na SO, iOS 5 zmienia sposób, w jaki wywołania zwrotne obrotu dla kontrolerów widoku podzielonego są wysyłane zgodnie z tą notatką wydania. Nie jest to dupe (chyba), bo nie może znaleźć innego pytanie na SO, który zajmuje się, jak dostosować widok podzielonego wykorzystanie kontrolera w iOS 5 do radzenia sobie ze zmianami:iOS5 przerywa wywołania zwrotne zwrotne UISplitViewController, jak wywołać ręcznie?

callbacków obrót w iOS 5 nie są stosowane do wyświetlania kontrolerów, które są wyświetlane na pełnym ekranie w postaci . Oznacza to, że jeśli Twój kod przedstawia kontroler widoku przez inny kontroler widoku, a następnie użytkownik następnie obraca urządzenie w inną orientację, po zwolnieniu , kontroler podstawowy (tj. Prezentujący kontroler) nie otrzyma żadnego obrotu callbacks. Należy jednak zauważyć, że prezentowany kontroler odbierze wywołanie viewWillLayoutSubviews po ponownym wyświetleniu go w postaci , a właściwość interfaceOrientation może być sprawdzana od tej metody i używana do prawidłowego rozmieszczenia kontrolera.

Mam problem z konfiguracją przycisku popover w moim kontroler widoku podziału root (ten, który ma wyświetlić widok z lewej strony w popover, gdy jesteś w portret). Oto jak moja sekwencja uruchamiania aplikacji wykorzystywane do pracy w iOS 4.x, gdy urządzenie jest w trybie poziomym:

  1. zainstalować kontroler widoku do podziału okna z [window addSubview:splitViewController.view]; [window makeKeyAndVisible];. Powoduje to, że splitViewController:willHideViewController:withBarButtonItem:forPopoverController: jest wywoływany na uczestniku (tj. Symulowanie krajobrazu -> rotacja portretu), nawet jeśli urządzenie jest już w trybie poziomym.

  2. Przedstaw pełnoekranowy modal (mój ekran ładowania), który całkowicie pokrywa widok podziału pod spodem.

  3. Zakończ ładowanie i odrzucanie modalnego ekranu ładowania. Ponieważ urządzenie znajduje się w trybie poziomym, po ujawnieniu kontrolera widoku podzielonego powoduje to wywołanie splitViewController:willShowViewController:invalidatingBarButtonItem: na delegacie (tj. Symulowanie portretu -> obrót krajobrazu), tym samym unieważniając element przycisku paska, usuwając go z prawej strony podzielonego widoku i pozostawiając nas tam, gdzie chcemy być. Brawo!

Tak, problem jest, że z powodu zmian opisanych w tej notatce uwalnianiu, co dzieje się wewnętrznie w iOS 4.3, który powoduje splitViewController:willShowViewController:invalidatingBarButtonItem: miano nie dzieje się w iOS 5. Próbowałem instacji UISplitViewController więc mogę zapewnić niestandardowa implementacja viewWillLayoutSubviews zgodnie z sugestią zawartą w dokumencie Release Notes, ale nie wiem, jak odtworzyć pożądaną sekwencję zdarzeń wewnętrznych wywoływanych przez iOS 4. Próbowałem tego:

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

To głównie działa, ale nie w 100%. Problem polega na tym, że samo wywołanie metody delegowania nie powoduje unieważnienia elementu przycisku paska, więc przy pierwszym obróceniu do portretu system uważa, że ​​element przycisku paska nadal jest poprawnie zainstalowany i nie próbuje go ponownie zainstalować. Dopiero po ponownym obróceniu do pejzażu, a następnie z powrotem do portretu, system wraca do właściwego stanu i faktycznie zainstaluje element przycisku paska popover w trybie pionowym.

Na podstawie this question próbowałem również ręcznie wywoływać wszystkie wywołania zwrotne rotacji zamiast uruchamiać metodę delegowania, np.:

// 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]; 
} 

jednak tylko wydaje to spowodować nieskończoną pętlę z powrotem do viewWillLayoutSubviews :(

Czy ktoś wie co jest poprawny sposób symulować iOS4 stylu zdarzenia obrotów jest dla kontrolera widoku podzielonego, który pojawia się od Czy w ogóle nie możesz ich symulować? Czy istnieje inne podejście, które stało się standardem dla iOS5?

Każda pomoc jest naprawdę doceniana, ponieważ ten problem powstrzymuje nas przed przesłaniem naszego iOS5 wydanie poprawki do App Store.

Odpowiedz

11

Nie znam właściwego sposobu radzenia sobie z tą sytuacją. Jednak dodaje wydaje się działać dla mnie w iOS 5.

  1. W splitViewController:willHideViewController:withBarButtonItem:forPopoverController: przechowywać odniesienie do barButtonItem w coś self.barButtonItem. Przenieś kod pokazujący przycisk do osobnej metody, powiedzmy ShowRootPopoverButtonItem.

  2. W splitViewController:willShowViewController:invalidatingBarButtonItem: wyczyść to odwołanie self.barButtonItem. Przenieś kod pokazujący przycisk do osobnej metody, powiedzmy InvalidateRootPopoverButtonItem.

  3. W viewWillLayoutSubviews ręcznie wyświetlić lub ukryć przycisk, w zależności od orientacji interfejsu

Oto moja realizacja viewWillLayoutSubviews. Pamiętaj, że wywoływanie self.interfaceOrientation zawsze zwróciło portret, stąd moje użycie statusBarOrientation.

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

Hej Noah - dzięki za rozwiązanie - to działa również dla mnie. To trochę niefortunne, ponieważ viewWillLayoutSubviews nazywa się znacznie częściej niż zdarzenia rotacyjne, więc wkuwanie wszystkich ukrytych/pokazujących logikę przycisku oznacza, że ​​uruchamia się o wiele częściej, ale wydaje się, że jest to sposób na iOS5-owski teraz te rzeczy. – glenc

Powiązane problemy