2010-10-13 1 views
5

Sto gestendo la mia UINavigationBar. Ho bisogno di farlo a causa di una vasta scuoiatura. La documentazione di UINavigationController avverte che esistono limitazioni alla skining di UINavigationBar quando utilizzato con un UINavigationController.UINavigationBar topItem/items sembra doppio-pop sul retro

Ho inserito una registrazione estesa e da tutto quello che posso dire, premendo il pulsante "Indietro" in UINavigationController vengono visualizzati due elementi fuori dallo stack anziché uno. Ricevo una singola chiamata di delegato che mi dice che sta rimuovendo l'elemento logico, ma in realtà rimuove quella e un'altra.

L'elemento aggiunto a UINavigationController in awakeFromNib deve essere mai rimosso. Viene rimosso per qualche motivo.

Ci sono due domande simili, ma nessuna ha risposte soddisfacenti. Le due domande sono:

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

A cura di aggiungere il debug rilevanti da un unico passaggio:

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

Ho esattamente lo stesso problema, ma ho lasciato che il controller di navigazione gestisca la mia barra di navigazione personalizzata. Hai trovato una risposta a questo? – mmmattias

risposta

0

Devi sempre chiamare [super awakeFromNib] quando la vostra sottoclasse implementa che metodo, per la documentazione di -awakeFromNib:

è necessario chiamare il super attuazione awakeFromNib per dare classi genitore la possibilità di compiere un ulteriore inizializzazione di cui hanno bisogno

È importante sottolineare, tuttavia, ...

Non capisco perché si devi effettivamente gestire la tua barra di navigazione. Se si sottoclasse lo UINavigationBar e si sovrascrivono solo determinati metodi di disegno o layout come -drawRect:, -layoutSubviews, ecc., Tutta la logica alla base della gestione della barra di navigazione in un controller di navigazione ricadrà sulla classe originale UINaviationBar.

Ho dovuto eseguire la personalizzazione della vista estesa per quasi tutte le principali classi UIKit, ma ho sempre lasciato la logica complicata alle classi originali, ignorando solo i metodi di disegno per personalizzare l'aspetto.

Per inciso, in realtà è molto più semplice applicare un'intera applicazione senza creare sottoclassi, se tutto ciò che si sta facendo è utilizzare risorse immagine personalizzate. Impostando la proprietà di un livello contents, è possibile personalizzare il look and feel di una classe basata su UIView su una base alle necessità o durante la vostra intera app:

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

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

È possibile impostare il contenuto per ogni classe che eredita da UIView: barre di navigazione, barre degli strumenti, pulsanti, ecc. È molto più facile da gestire in questo modo senza dover creare una sottoclasse.

+0

Dalla documentazione di UINavigationBar: Se utilizzato in combinazione con un controller di navigazione, sono disponibili solo alcune personalizzazioni dirette alla barra di navigazione. In particolare, è bene modificare le proprietà barStyle, tintColor e traslucenti di questa classe, ma non è mai necessario modificare direttamente le proprietà a livello di UIView come frame, bound, alpha o proprietà nascoste. Inoltre, dovresti lasciare che il controller di navigazione gestisca la pila di elementi di navigazione e non tentare di modificare questi elementi tu stesso. –

+0

La modifica della proprietà 'contents' del livello della vista è completamente a posto. Fidati di me, ho usato la tecnica che ho postato sopra in diversi casi per modificare solo l'aspetto delle mie barre di navigazione, lasciando solo il resto delle loro caratteristiche: pulsanti, spingere/scoppiare, titoli, ecc. In effetti, questo è lo scopo esatto di fornire un 'calayer' di supporto per tutti gli oggetti' UIView'. – LucasTizma

0

Questo sembra essere un errore nell'implementazione di -[UINavigationBar items]

Quando chiamato dall'interno del metodo -navigationBar:didPopItem: delegato, esso omettere l'ultimo oggetto.È possibile controllare questo chiamando [navigationBar valueForKey:@"_itemStack"] per recuperare l'array sottostante e vedere che gli elementi previsti sono ancora lì.

L'aggiunta di un dispatch_async all'interno del metodo -navigationBar:didPopItem: risolve correttamente il problema nella mia app.