2010-10-13 15 views
5

Zarządzam moim własnym UINavigationBar. Muszę to zrobić ze względu na rozległe skórki. Dokumentacja dla UINavigationController ostrzega, że ​​istnieją ograniczenia dotyczące skórowania paska UINavigationBar, gdy jest on używany z kontrolerem UINavigationController.UINavigationBar topItem/items wydaje się podwójnie pop z tyłu

Wprowadziłem obszerne rejestrowanie i ze wszystkiego, co widzę, naciśnięcie przycisku "Wstecz" w panelu UINavigationController powoduje wyjęcie dwóch elementów ze stosu zamiast jednego. Otrzymuję pojedyncze wywołanie od uczestnika mówiące mi, że usuwa on element logiczny, ale faktycznie usuwa ten jeden i jeszcze jeden.

Element dodany do elementu UINavigationController w awakeFromNib powinien być nigdy nie może być usunięty. Jest usuwany z jakiegoś powodu.

Istnieją dwa podobne pytania, ale nie ma zadowalających odpowiedzi. Te dwa pytania:

UINavigationBar .items accessor doesn't return the current UINavigationItem

UINavigationBar seems to pop 2 items off stack on "back"

- (void)awakeFromNib { 
    [headerView setDelegate: self]; 
    [headerView pushNavigationItem: tableDisplay animated: NO]; 
} 

- (void) selectedStory: (NSNotification *)not { 
    [headerView pushNavigationItem: base animated: NO]; 
    NSLog(@"Selected story: %@", base); 
} 

- (void) baseNav { 
    NSLog(@"Current items: %@", [headerView items]); 
    BaseInnerItem *current = (BaseInnerItem *)[headerView topItem]; 
    [self addSubview: [current view]]; 
} 

- (BOOL)navigationBar: (UINavigationBar *)navigationBar shouldPushItem: (UINavigationItem *)item { 
    return YES; 
} 

- (BOOL)navigationBar: (UINavigationBar *)navigationBar shouldPopItem: (UINavigationItem *)item { 
    return YES; 
} 

- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item { 
    NSLog(@"didPushItem: %@", item); 
    [self baseNav]; 
} 

- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item { 
    NSLog(@"didPopItem: %@", item); 
    [self baseNav]; 
} 

Edited by dodać odpowiednie debugowanie z jednego biegu:

2010-10-13 02:12:45.911 Remix2[17037:207] didPushItem: <TableDisplay: 0x5d41cc0> 
2010-10-13 02:12:45.912 Remix2[17037:207] Current items: (
    "<TableDisplay: 0x5d41cc0>" 
) 
2010-10-13 02:12:49.020 Remix2[17037:207] didPushItem: <WebDisplay: 0x591a590> 
2010-10-13 02:12:49.021 Remix2[17037:207] Current items: (
    "<TableDisplay: 0x5d41cc0>", 
    "<WebDisplay: 0x591a590>" 
) 
2010-10-13 02:12:49.023 Remix2[17037:207] Selected story: <WebDisplay: 0x591a590> 
2010-10-13 02:12:59.498 Remix2[17037:207] didPopItem: <WebDisplay: 0x591a590> 
2010-10-13 02:12:59.499 Remix2[17037:207] Current items: (
) 
+0

Mam dokładnie ten sam problem, ale pozwoliłem kontrolerowi nawigacji obsłużyć mój niestandardowy pasek nawigacji ze skórą. Czy znalazłeś odpowiedź na to pytanie? – mmmattias

Odpowiedz

0

Zawsze trzeba zadzwonić [super awakeFromNib] gdy podklasa implementuje że metoda, zgodnie z dokumentacją dla -awakeFromNib:

Należy zadzwonić super realizację awakeFromNib dać klas dominującej możliwość wykonywania jakichkolwiek dodatkowych inicjalizacji wymagają one

ważniejsze, ...

Nie rozumiem dlaczego Muszę zarządzać własnym paskiem nawigacyjnym. Jeśli podklasa UINavigationBar i tylko zastąpi niektóre metody rysowania lub układu, takie jak -drawRect:, -layoutSubviews itd., Wówczas cała logika zarządzania paskiem nawigacji w kontrolerze nawigacyjnym po prostu powróci do oryginalnej klasy UINaviationBar.

Musiałem wykonać szczegółowe dostosowywanie widoku dla prawie każdej ważnej klasy UIKit, ale zawsze pozostawiałem skomplikowaną logikę oryginalnym klasom, zastępując tylko metody rysowania, aby dostosować wygląd i styl.

Nawiasem mówiąc, o wiele łatwiej jest skasować całą aplikację bez tworzenia podklas, jeśli wszystko, co robisz, to używanie niestandardowych zasobów graficznych. Poprzez ustawienie warstwą za contents właściwość, można dostosować wygląd i styl UIView opartym klasy na miarę potrzeb lub na wskroś całej aplikacji:

#import <QuartzCore/QuartzCore.h> 
... 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    UIImage * navigationBarContents = [UIImage imageNamed:@"navigation-bar"]; 
    self.navigationController.navigationBar.layer.contents =  
     (id)navigationBarContents.CGImage; 
} 

Można ustawić zawartość do dowolnej klasy, która dziedziczy od UIView: paski nawigacyjne, paski narzędzi, przyciski itp. O wiele łatwiej jest zarządzać w ten sposób bez konieczności korzystania z podklasy.

+0

Z dokumentacji UINavigationBar: W połączeniu z kontrolerem nawigacyjnym istnieje tylko kilka bezpośrednich dostosowań do paska nawigacji. W szczególności można modyfikować właściwości barStyle, tintColor i półprzezroczyste tej klasy, ale nie wolno bezpośrednio zmieniać właściwości poziomu UIView, takich jak właściwości ramki, ograniczeń, alfa lub ukrytych. Ponadto powinieneś pozwolić kontrolerowi nawigacyjnemu zarządzać stosem elementów nawigacyjnych i nie próbować samodzielnie modyfikować tych elementów. –

+0

Modyfikowanie właściwości 'content' warstwy widoku jest całkowicie w porządku pod tym względem. Zaufaj mi, użyłem techniki, którą napisałem powyżej w kilku przypadkach, aby zmodyfikować tylko wygląd moich pasków nawigacyjnych, pozostawiając całą resztę ich cech: przyciski, pchanie/popping, tytuły, itd. Rzeczywiście, to jest dokładny cel dostarczania podkładu 'CALayer' dla wszystkich obiektów' UIView'. – LucasTizma

0

Wydaje się to być błąd w realizacji -[UINavigationBar items]

Wywołany od wewnątrz metody -navigationBar:didPopItem: delegata, to pominięcie ostatniego obiektu.Możesz to sprawdzić, wywołując [navigationBar valueForKey:@"_itemStack"], aby pobrać tablicę bazową i zobaczyć, że oczekiwane elementy nadal tam są.

Dodanie metody dispatch_async w ramach metody -navigationBar:didPopItem: skutecznie obejmie problem w mojej aplikacji.

Powiązane problemy