UITableView: viewForHeaderInSection: non chiamato durante reloadData:


127

Ho impostato la vista tabella con collegamenti delegato e origine dati corretti. Il metodo reloadData chiama l'origine dati e i metodi delegato tranne viewForHeaderInSection:.

Perchè è così?


30
L' heightForHeaderInSection:implementazione è?
7usam

Hai impostato un valore per TableView sectionHeaderHeight?
Carter Medlin,

Risposte:


256

L'uso di tableView:viewForHeaderInSection:richiede anche l'implementazione tableView:heightForHeaderInSection:. Ciò dovrebbe restituire un'altezza diversa da zero appropriata per l'intestazione. Assicurati anche di non implementare anche il tableView:titleForHeaderInSection:. Dovresti usare solo l'uno o l'altro ( viewForHeadero titleForHeader).


3
Assicurati che non ci sia un refuso nella firma del metodo. Una lettera sbagliata significa che non verrà chiamata. Controlla anche il caso. Assicurati anche di restituire 0 da numberOfSections.
rmaddy,

tutto è corretto e si compila correttamente .. il problema che volevo capire riguarda i tempi di quando il metodo è chiamato .. tableView: viewForHeaderInSection viene chiamato quando la tabella sta per essere visualizzata e non come parte dell'esecuzione della sincronizzazione di [ tableview reloadData]
inforeqd,

@maddy OMG Grazie, è così stupido da parte mia che ho creato le mie istanze ma non ho aggiunto al mio array
Happiehappie

4
Puoi assolutamente avere entrambi. viewForHeaderInSection: avrà la precedenza sul titoloForHeaderInSection: l'unico requisito è impostare stimaSectionHeaderHeight sulla vista della tabella con qualcosa di diverso da 0, altrimenti viewForHeaderInSection: non verrà mai chiamato
Romrom

Aggiungendo al commento di @ romrom: se sono stati implementati entrambi titleForHeaderInSection:e se viewForHeaderInSection:la vista restituita da quest'ultima è una sottoclasse di UITableViewHeaderFooterViewallora textLabel.textviene automaticamente impostata sulla versione maiuscola della titleForHeaderInSection:stringa. Per impedire questo comportamento, non implementare titleForHeaderInSection:né utilizzare un'etichetta personalizzata anziché ereditata textLabel.
Ortwin Gentz,

40

Il trucco è che questi due metodi appartengono a UITableViewprotocolli diversi : tableView:titleForHeaderInSection:è un UITableViewDataSourcemetodo di protocollo, a cui tableView:viewForHeaderInSectionappartiene UITableViewDelegate.

Questo significa:

  • Se implementate i metodi ma vi assegnate solo come dataSourceper il UITableView, l' tableView:viewForHeaderInSectionimplementazione verrà ignorata.

  • tableView:viewForHeaderInSectionha una priorità più alta. Se si implementa entrambi i metodi e assegnare te stesso come sia la dataSourcee delegateper la UITableView, si tornerà il punto di vista per intestazioni di sezione, ma il vostro tableView:titleForHeaderInSection:sarà ignorato.

Ho anche provato a rimuovere tableView:heightForHeaderInSection:; ha funzionato bene e non sembra aver influenzato le procedure sopra. Ma la documentazione afferma che è necessario per il tableView:viewForHeaderInSectioncorretto funzionamento; quindi per sicurezza è opportuno implementare anche questo.


6
Mi hai reso felice !!! Ho dimenticato di assegnare UITableViewDelegatea self, perché ho pensato, che tableView:viewForHeaderInSectionè un UITableViewDataSourcemetodo. Grazie!
denis631

1
"tableView: viewForHeaderInSection" non è vitale. Ciò che è vitale è in qualche modo restituire un'altezza. Puoi ottenerlo attraverso 1. stima o 2. un valore hardcoded o 3. a titleForHeaderche ha una dimensione intrinseca. La dimensione intrinseca viene calcolata in base alla famiglia e alla dimensione del carattere.
Miele

28

@rmaddy ha errati la regola, due volte: in realtà, tableView:viewForHeaderInSection:non senza richiedere che anche di implementare tableView:heightForHeaderInSection:, ed inoltre è perfettamente bene di chiamare sia titleForHeadereviewForHeader . Dichiarerò la regola correttamente solo per la cronaca:

La regola è semplicemente che viewForHeadernon verrà chiamata a meno che tu non dia in qualche modo altezza all'intestazione. Puoi farlo in qualsiasi combinazione di tre modi:

  • Implementare tableView:heightForHeaderInSection:.

  • Prepara il tavolo sectionHeaderHeight.

  • Chiama titleForHeader(questo in qualche modo dà all'intestazione un'altezza predefinita se non ne ha altrimenti).

Se non fai nessuna di queste cose, non avrai intestazioni e viewForHeadernon verrai chiamato. Questo perché senza un'altezza, il runtime non saprà come ridimensionare la vista, quindi non si preoccupa di richiederne uno.


Dai documenti per tableView:viewForHeaderInSection:: "Questo metodo funziona correttamente solo quando tableView:heightForHeaderInSection:è implementato."
rmaddy,

1
Belle. Quello che dicono i documenti, dicono. Adesso sperimenta. I fatti sono come ho affermato.
opaco

E come puoi avere entrambi titleForHeaderInSectione viewForHeaderInSection? La vista tabella chiamerà solo una delle due (dimentico quale al momento ha la precedenza).
rmaddy,

1
In realtà c'è un altro pezzo del puzzle, che a volte viewForHeader viene chiamato senza nessuno di quei tre modi di assegnare un'altezza. Ho avuto questo accadere, dove il mio è viewForHeaderstato chiamato e le intestazioni si sono presentate bene, fino a quando un giorno, senza alcun cambiamento da parte mia, non lo hanno fatto . In quel momento ho iniziato a sperimentare per scoprire quali sono i requisiti minimi per viewForHeaderessere chiamati. E ora lo so. E ora anche tu.
opaco

2
@texas No, non faccio xamarin. L'aggiunta di un altro livello di riferimento indiretto ai framework Cocoa mi farebbe esplodere la testa. :)
matt

20

Dare estimatedSectionHeaderHeighte sectionHeaderHeightvalori hanno risolto il mio problema. per esempio, self.tableView.estimatedSectionHeaderHeight = 100 self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension


Il mio problema è iniziato dopo l'aggiornamento a Swift 3.1. Questa soluzione l'ha risolto.
Zevij,

@pbuchheit Apple Docs afferma che è disponibile da iOS 7.0+, per favore dai un'occhiata qui, developer.apple.com/documentation/uikit/uitableview/…
Sharukh Mastan

@Sharukh Mastan Sembra che tu abbia ragione. Per qualche motivo stavo ricevendo un avviso quando ho provato a usare quella proprietà, ma è andata via dopo aver fatto una build pulita.
pbuchheit,

7

Uscendo dalla risposta di rmaddy, stavo cercando di nascondere la vista Header e stavo restituendo 0.0f per "tableView: heightForHeaderInSection" e una vista 0 altezza da tableView:viewForHeaderInSection.

Dopo essere passato da return 1.0fa return 0.0fin tableView:heightForHeaderInSection, è tableView:viewForHeaderInSectionstato effettivamente chiamato il metodo delegato .

Risulta che l'effetto desiderato funziona senza dover usare "tableView: heightForHeaderInSection"; ma questo può essere utile per gli altri che stanno riscontrando problemi nell'ottenere il metodo delegato "tableView: heightForHeaderInSection".


5

Dovresti implementare tableView:heightForHeaderInSection: e impostare l'altezza per l'intestazione> 0.

Questo metodo delegato si accompagna a viewForHeaderInSection: metodo.

Spero che aiuti.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
         return 40;
}

Hai provato che la tua risposta funziona davvero? Becaus e se leggi attentamente, allora si afferma che inizialmente viene chiamato viewForHeaderInSection. Non viene chiamato solo quando la tabella viene ricaricata!
Karlis,

5

Vale la pena notare brevemente che se la tua implementazione di tableView:heightForHeaderInSection:resi UITableViewAutomaticDimension, alloratableView:viewForHeaderInSection: non verrà chiamata.

UITableViewAutomaticDimensionpresuppone che UITableViewHeaderFooterViewverrà utilizzato uno standard popolato con il metodo delegato tableView:titleForHeaderInSection:.

Dai commenti in UITableView.h:

La restituzione di questo valore da tableView:heightForHeaderInSection:o tableView:heightForFooterInSection:risulta in un'altezza adatta al valore restituito da tableView:titleForHeaderInSection:o tableView:titleForFooterInSection:se il titolo non è zero.


1
se si imposta estimatedSectionHeaderHeightsu un valore, tableView:viewForHeaderInSectionverrà chiamato (analogamente a come funzionano le dimensioni automatiche per le righe)
GreatWiz,

Interessante, grazie. A 7.1 questa sottigliezza dell'altezza stimata era importante per le celle , quindi potrebbe essere stato il caso anche per le intestazioni, ma non è terribilmente rilevante ora!
Benjohn,

3

Ho appena avuto un problema con le intestazioni che non vengono visualizzate per iOS 7.1 , ma lavorando bene con le versioni successive che ho testato, esplicitamente con 8.1 e 8.4.

Per lo stesso identico codice, 7.1 non chiamava affatto nessuno dei metodi delegati dell'intestazione di sezione, inclusi: tableView:heightForHeaderInSection:e tableView:viewForHeaderInSection:.

Dopo la sperimentazione, ho scoperto che la rimozione di questa riga dalle viewDidLoadintestazioni create riappariva per 7.1 e non ha avuto alcun impatto su altre versioni che ho testato:

// _Removing_ this line _fixed_ headers on 7.1
self.tableView.estimatedSectionHeaderHeight = 80;

... quindi, sembra esserci un qualche tipo di conflitto lì per 7.1, almeno.


3

Lo stesso problema si è verificato con me, ma poiché stavo usando il calcolo automatico dell'altezza da xCode 9 , non posso fornire alcun valore di altezza esplicito come menzionato sopra. Dopo un po 'di sperimentazione ho ottenuto una soluzione , dobbiamo ignorare questo metodo come

-(CGFloat)tableView:(UITableView *)tableView 
         estimatedHeightForHeaderInSection:(NSInteger)section
{
      return 44.0f;
}

Anche se ho controllato entrambe le opzioni

  1. Calcolo automatico dell'altezza
  2. Calcolo automatico dell'altezza stimata

dallo storyboard come dice apple, ma ho ancora questo strano errore.

Nota : questo errore è stato mostrato solo sulla versione IOS-10 e non sulla versione IOS-11 . Forse è un bug di xCode. Grazie


0

Ecco cosa ho trovato ( Swift 4 ) (grazie a questo commento su un'altra domanda)

Sia che avessi usato titleForHeaderInSection o viewForHeaderInSection - non era che non venivano richiamati quando si scorreva la vista tabella e venivano caricate nuove celle, ma tutte le scelte di carattere che avevo fatto per l'etichetta text di headerView comparivano solo su ciò che era inizialmente visibile al caricamento e non durante lo scorrimento della tabella.

La correzione era willDisplayHeaderView:

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    if let header = view as? UITableViewHeaderFooterView {
        header.textLabel?.font = UIFont(name: yourFont, size: 42)
    }
}

0

Nel mio caso ho creato la vista dell'intestazione usando UITableviewCelle restituendo la cella in viewForHeaderInSectionquesto modo

return cell

modificato in

return cell.contentView 

Ha funzionato per me.


0

Nel mio caso

viewForHeaderInSection

è stato implementato in una classe derivata molto lontana che non si preoccupava di creare una superclasse.


0

Il motivo per cui viewForHeaderInSectionnon viene chiamato è per uno dei due motivi:

O non hai impostato il tuo UITableViewDelegateo hai impostato il tuo in UITableViewDelegatemodo errato.


0

Nel mio caso è stato perché non ho implementato:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat

-1

A volte l'impostazione tableview.delegateo datasource = nilnei metodi viewWillAppear:o viewDidAppear:può causare questo problema. Assicurati di non farlo ...


-1

Ho tagliato e incollato i seguenti due metodi da un progetto Swift 2 nel mio progetto Swift 3 che non sono mai stati chiamati perché in Swift 3 questi metodi devono avere "-" prima del nome del primo parametro.

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 44.0
}

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: B2BTrolleyHeaderFooterView.reuseIdentifier) as! B2BTrolleyHeaderFooterView        
    return headerView
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.