2013-09-22 12 views
16

Ho un modulo di visualizzazione tabella creato utilizzando le celle statiche in IB/Storyboard. Tuttavia, ho bisogno di nascondere alcune celle in fase di esecuzione a seconda di determinate condizioni.Nascondi celle in UITableView con celle statiche e nessun arresto anomalo automatico

Ho trovato un po 'di risposte; a questa domanda su SO, ad es.

UITableView set to static cells. Is it possible to hide some of the cells programmatically?

.. e si concentrano su come impostare l'altezza della cella/riga a 0. Questo è grande, tranne che io ora ottenere eccezioni layout automatico, perché i vincoli non possono essere soddisfatte. Come faccio ad aggirare questo ultimo problema? Posso disabilitare temporaneamente Auto-Layout per una sottoview? C'è un modo migliore per farlo in iOS7?

risposta

14

Ho trovato che il modo migliore per farlo è quello di gestire semplicemente numberOfRowsInSection, cellForRowAtIndexPath e heightForRowAtIndexPath per eliminare selettivamente determinate righe. Ecco un esempio 'hardcoded' per il mio scenario, si potrebbe fare qualcosa di un po 'più intelligente per rimuovere in modo intelligente determinate celle piuttosto che un codice hard come questo, ma questo è stato il più semplice per il mio semplice scenario.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 
    if (indexPath.section == 0 && hideStuff) { 
     cell = self.cellIWantToShow; 
    } 
    return cell; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    CGFloat height = [super tableView:tableView heightForRowAtIndexPath:indexPath]; 
    if (indexPath.section == 0 && hideStuff) { 
     height = [super tableView:tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; 
    } 
    return height; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    NSInteger count = [super tableView:tableView numberOfRowsInSection:section]; 

    if (section == 0 && hideStuff) { 
     count -= hiddenCells.count; 
    } 

    return count; 
} 
+0

Felice di averlo risolto, mi sentivo in colpa per la mia vecchia "risposta" che non funzionava! – jrturton

+4

Può funzionare, ma penso che non sia supportato, come dice la guida alla programmazione di Apple Table View "Se una vista tabella in uno storyboard è statica, la sottoclasse personalizzata di UITableViewController che contiene la vista tabella non dovrebbe implementare il protocollo dell'origine dati." (da https://developer.apple.com/library/ios/documentation/userexperience/conceptual/tableview_iphone/CreateConfigureTableView/CreateConfigureTableView.html#//apple_ref/doc/uid/TP40007451-CH6-SW27). Questi metodi provengono tutti dal protocollo dell'origine dati. In altre parole, non c'è garanzia che questa soluzione non si rompa quando Apple aggiorna le cose. – algal

+0

Questo sembra non funzionare in iOS 8. La console emette un avviso, che il delegato è implementato per la vista tabella statica e questo è probabilmente per errore e ignorerà il delegato. Grazie, Apple! – osxdirk

2

Il modo kosher per fare ciò è utilizzare celle dinamiche, impostare l'altezza della riga su 0 è un hack. Le celle statiche sono molto comode ma limitate nella funzionalità.

+2

Per fare ciò con le celle dinamiche inviare la complessità della forma attraverso il tetto. Non credo che non ci sia una soluzione migliore, anche se la complessità delle celle nascoste è alta, la complessità totale (e quindi la manutenibilità) sarà ancora inferiore a me avendo questa grande forma resa tramite celle dinamiche (che posso vediamo in IB). A meno che tu non conosca un buon modo per farlo con Dynamic Cells pur continuando a supportare IB e punti vendita ecc. – ConfusedNoob

+0

Puoi ancora utilizzare le prese IB con prototipi di celle dinamiche nello storyboard. Hai solo bisogno di sottoclasse 'UITableCell' e controlla il trascinamento delle uscite nella nuova sotto classe. Poi nella tua vista tabella il controller accederà alla proprietà. – GayleDDS

2

Se si assicura non c'è vincolo di toccare il bordo inferiore della cella, AutoLayout non deve barf (testato su iOS 6.0, 6.1, 7.0). Continuerai ad ancorare al limite superiore e dovrai appuntare le altezze. (Puoi fare il contrario e ancorare in fondo, ovviamente.)

Se il tuo layout dipende dalle posizioni di bordo superiore e inferiore, potrebbe essere possibile rimuovere i vincoli a livello di codice (sono solo oggetti, dopo tutti).

+0

Questo ha funzionato per me. La risposta di ConfusedNoob sembrerebbe più appropriata. Ma dal momento che sto usando Xamarin, non ho potuto farlo funzionare facilmente. – m1sk

+0

Un modo migliore è quello di modificare il vincolo di base su <= in opposizione a ==. – Joey

1

Sono riuscito ad evitare eccezioni dal layout automatico rimuovendo prima i vincoli sul contentView della cella a livello di programmazione in viewDidLoad e quindi impostando l'altezza della cella su 0 in heightForRowAtIndexPath.

3

Il modo più semplice è quello di modificare l'altezza di sezioni e file. Per me funziona.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 
{ 
    if (section == 3) { 
     return 0; 
    } else { 
     return [super tableView:tableView heightForHeaderInSection:section]; 
    } 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 
    if (indexPath.section == 3) { 
     cell.hidden = YES; 
     return 0; 
    } else { 
     cell.hidden = NO; 
     return [super tableView:tableView heightForRowAtIndexPath:indexPath]; 
    } 
} 
0

Il modo migliore per me era modificare il metodo numberOfRowsInSection. Ho rimosso l'origine dati che non volevo visualizzare. La migliore soluzione per me, perché tutto è in una funzione.

(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
if(section==0) { 
    NSUInteger productCount = _products.count; 
    for(loop trough your data) { 
     if(your condition is true) 
     productCount--; 
     } 
    } 
    return productCount; 
} else 
    return self.groups.count; 
} 
0

Implementato anche questo, per una vista tabella in uno StoryBoard. Le mie celle sono incorporate in sezioni con un'intestazione, rappresentata da quel cubo blu in xcode6 IB. Infatti, se si implementa heightForHeaderInSection, heightForFooterInSection e titleForHeaderInSection, titleForFooterInSection è possibile accedere alle intestazioni quando viene visualizzata la tabella e restituire rispettivamente 0.0 e nil e restituire 0 per numberOfRowsInSection.

Fondamentalmente funziona tutto bene, tranne che per ogni cella nascosta a ca. Lo spazio verticale alto 10 pixel rimane per ogni cella (sezione) nascosta. Qualche idea di cosa potrebbe essere?

7

Nascondi le celle storyboard e impostare l'altezza a 0:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 
    let cell: UITableViewCell = super.tableView(tableView, cellForRowAtIndexPath:indexPath) 
    return cell.hidden ? 0 : super.tableView(tableView, heightForRowAtIndexPath:indexPath) 
    } 
} 
+0

Genio! La migliore risposta finora –

1

ho trovato un modo che permette anche remate animazioni e sta lavorando su iOS 8.3.Tutto ciò che serve è quello di implementare il tableView: Metodo di origine dati e quindi aggiungere/eliminare la riga con metodi UITableView insertRowsAtIndexPaths:: numberOfRowsInSection withRowAnimation: e deleteRowsAtIndexPaths: withRowAnimation:.

Ecco esempio di nascondere fila esatta basata sul UISwitch stato:

- (IBAction)alowNotif:(id)sender { 
    UISwitch *sw = (UISwitch*)sender; 
    NSIndexPath *index = [NSIndexPath indexPathForRow:5 inSection:0]; 
    if ([sw isOn]) { 
     [self.tableView insertRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationAutomatic]; 
    } 
    else { 
     [self.tableView deleteRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationAutomatic]; 
    } 
} 

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    if (![notifications isOn]) { 
     return 5; 
    } 
    return 6; 
} 

Come già detto da @algal, numberOfRowInSection: è ancora UITableViewDataSource metodo, quindi uno non sa semplicemente per quanto tempo lavorerà.

Problemi correlati