UITableView: viewForHeaderInSection: Wird während reloadData nicht aufgerufen:

127

Ich habe die Tabellenansicht mit korrekten Delegaten- und Datenquellenverknüpfungen eingerichtet. Die reloadData-Methode ruft die Datenquellen- und die Delegatenmethode mit Ausnahme von auf viewForHeaderInSection:.

Warum ist das so?

inforeqd
quelle
30
Ist das heightForHeaderInSection:implementiert?
7usam
Haben Sie einen Wert für die TableViews festgelegt sectionHeaderHeight?
Carter Medlin

Antworten:

256

Die Verwendung von tableView:viewForHeaderInSection:erfordert, dass Sie auch implementieren tableView:heightForHeaderInSection:. Dies sollte eine geeignete Höhe ungleich Null für den Header zurückgeben. Stellen Sie außerdem sicher, dass Sie das nicht auch implementieren tableView:titleForHeaderInSection:. Sie sollten nur das eine oder andere ( viewForHeaderoder titleForHeader) verwenden.

rmaddy
quelle
3
Stellen Sie sicher, dass die Signatur der Methode keinen Tippfehler enthält. Ein falscher Buchstabe bedeutet, dass er nicht aufgerufen wird. Überprüfen Sie auch den Fall. Stellen Sie außerdem sicher, dass Sie 0 von zurückgeben numberOfSections.
rmaddy
Alles ist korrekt und wird korrekt kompiliert. Das Problem, das ich verstehen wollte, ist der Zeitpunkt, zu dem die Methode aufgerufen wird. tableView: viewForHeaderInSection wird aufgerufen, wenn die Tabelle gerade angezeigt werden soll und nicht als Teil der Synchronisierungsausführung von [ tableview reloadData]
inforeqd
@maddy OMG Danke, es ist so dumm von mir, dass ich meine Instanzen erstellt habe, aber ich habe nicht an mein Array
angehängt
4
Sie können absolut beides haben. viewForHeaderInSection: hat Vorrang vor titleForHeaderInSection: Die einzige Voraussetzung ist, dass Sie geschätzteSectionHeaderHeight in Ihrer Tabellenansicht mit etwas anderem als 0 festlegen, andernfalls wird viewForHeaderInSection: nie aufgerufen
vom
Das Hinzufügen @ romrom Kommentar: Wenn Sie implementiert haben beide titleForHeaderInSection:und viewForHeaderInSection:und die Aussicht von dieser zurückgegeben wird , ist eine Unterklasse von UITableViewHeaderFooterViewdann seine textLabel.textautomatisch auf die alle Caps Version der titleForHeaderInSection:Zeichenfolge. Um dieses Verhalten zu verhindern, implementieren titleForHeaderInSection:oder verwenden Sie keine benutzerdefinierte Bezeichnung anstelle der geerbten textLabel.
Ortwin Gentz
40

Der Trick ist, dass diese beiden Methoden zu unterschiedlichen UITableViewProtokollen gehören: tableView:titleForHeaderInSection:ist eine UITableViewDataSourceProtokollmethode, zu der tableView:viewForHeaderInSectiongehört UITableViewDelegate.

Das bedeutet:

  • Wenn Sie die Methoden implementieren, sich aber nur als dataSourcefür die zuweisen UITableView, wird Ihre tableView:viewForHeaderInSectionImplementierung ignoriert.

  • tableView:viewForHeaderInSectionhat eine höhere Priorität. Wenn Sie beide Methoden implementieren und sich sowohl als dataSourceals auch als delegatefür die zuweisen UITableView, geben Sie die Ansichten für Abschnittsüberschriften zurück, Ihre tableView:titleForHeaderInSection:werden jedoch ignoriert.

Ich habe auch versucht, zu entfernen tableView:heightForHeaderInSection:; es funktionierte gut und schien die oben beschriebenen Verfahren nicht zu beeinflussen. Die Dokumentation besagt jedoch, dass es erforderlich ist, damit das tableView:viewForHeaderInSectionordnungsgemäß funktioniert. Um sicher zu gehen, ist es auch ratsam, dies umzusetzen.

Yunus Nedim Mehel
quelle
6
Du hast meinen Tag gerettet!!! Vergessen zuweisen UITableViewDelegatezu self, weil ich dachte, das tableView:viewForHeaderInSectionist ein UITableViewDataSourceVerfahren. Danke dir!
denis631
1
"tableView: viewForHeaderInSection" ist nicht wichtig. Was wichtig ist, ist, dass Sie irgendwie eine Höhe zurückgeben. Sie können dies entweder durch 1. Schätzung oder 2. einen fest codierten Wert oder 3. a erreichen, titleForHeaderder eine intrinsische Größe hat. Die intrinsische Größe wird basierend auf der Schriftfamilie und -größe berechnet.
Honig
28

@rmaddy hat die Regel zweimal falsch angegeben: In Wirklichkeit ist tableView:viewForHeaderInSection:es nicht erforderlich, dass Sie auch implementieren tableView:heightForHeaderInSection:, und es ist auch vollkommen in Ordnung, beide titleForHeaderund aufzurufen viewForHeader. Ich werde die Regel nur für die Aufzeichnung korrekt angeben:

Die Regel ist einfach, dass viewForHeadernicht aufgerufen wird, es sei denn, Sie geben dem Header irgendwie eine Höhe. Sie können dies auf drei Arten tun:

  • Implementieren tableView:heightForHeaderInSection:.

  • Stellen Sie die Tische ein sectionHeaderHeight.

  • Aufruf titleForHeader(dies gibt dem Header irgendwie eine Standardhöhe, wenn er sonst keine hat).

Wenn Sie keines dieser Dinge tun, haben Sie keine Überschriften und viewForHeaderwerden nicht aufgerufen. Das liegt daran, dass die Laufzeit ohne Höhe nicht weiß, wie die Größe der Ansicht geändert werden soll, sodass sie nicht nach einer solchen fragen muss.

matt
quelle
Aus den Dokumenten für tableView:viewForHeaderInSection:: "Diese Methode funktioniert nur dann korrekt, wenn sie tableView:heightForHeaderInSection:auch implementiert ist."
rmaddy
1
Fein. Was die Dokumente sagen, sagen sie. Jetzt experimentieren. Die Fakten sind wie ich angegeben habe.
Matt
Und wie kannst du beides haben titleForHeaderInSectionund viewForHeaderInSection? In der Tabellenansicht wird nur eine der beiden aufgerufen (ich vergesse, welche im Moment Vorrang hat).
rmaddy
1
Tatsächlich gibt es noch einen Teil des Puzzles, der manchmal ohne eine dieser drei Möglichkeiten zum Zuweisen einer Höhe viewForHeaderaufgerufen wird . Ich hatte dies geschehen, wo meine aufgerufen wurden und die Überschriften gut auftauchten, bis sie eines Tages ohne Änderung meinerseits dies nicht taten . Zu diesem Zeitpunkt begann ich zu experimentieren, um herauszufinden, welche Mindestanforderungen zu nennen sind . Und jetzt weiß ich es. Und jetzt auch du. viewForHeaderviewForHeader
Matt
2
@texas Nein, ich mache kein Xamarin. Das Hinzufügen einer weiteren Indirektionsebene über die Cocoa-Frameworks würde meinen Kopf explodieren lassen. :)
Matt
20

Geben estimatedSectionHeaderHeightund sectionHeaderHeightWerte haben mein Problem behoben. z.B, self.tableView.estimatedSectionHeaderHeight = 100 self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension

Sharukh Mastan
quelle
Mein Problem begann nach dem Upgrade auf Swift 3.1. Diese Lösung hat es behoben.
Zevij
@pbuchheit Apple Docs sagt, dass es von iOS 7.0+ verfügbar ist. Bitte schauen Sie hier, developer.apple.com/documentation/uikit/uitableview/…
Sharukh Mastan
@ Sharukh Mastan Sieht aus wie Sie richtig sind. Aus irgendeinem Grund erhielt ich eine Warnung, als ich versuchte, diese Eigenschaft zu verwenden, aber sie verschwand nach einem sauberen Build.
pbuchheit
7

Als ich von der Antwort von rmaddy abging, versuchte ich, die Header-Ansicht auszublenden und gab 0.0f für "tableView: heightForHeaderInSection" und eine 0-height-Ansicht von zurück tableView:viewForHeaderInSection.

Nach dem Wechsel von return 1.0fzu return 0.0fin tableView:heightForHeaderInSectionwurde die Delegate-Methode tableView:viewForHeaderInSectiontatsächlich aufgerufen.

Es stellt sich heraus, dass mein gewünschter Effekt funktioniert, ohne "tableView: heightForHeaderInSection" verwenden zu müssen. Dies kann jedoch für andere nützlich sein, die Probleme beim Aufrufen der Delegatenmethode "tableView: heightForHeaderInSection" haben.

rrrrrraul
quelle
5

Sie sollten tableView:heightForHeaderInSection:die Höhe für den Header> 0 implementieren und festlegen.

Diese Delegatmethode geht mit der viewForHeaderInSection:Methode einher .

Ich hoffe das hilft.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
         return 40;
}
Chiara
quelle
Haben Sie getestet, dass Ihre Antwort tatsächlich funktioniert? Wenn Sie sorgfältig lesen, wird angegeben, dass zunächst viewForHeaderInSection aufgerufen wird. Es wird nicht nur aufgerufen, wenn die Tabelle neu geladen wird!
Karlis
5

Es lohnt sich kurz darauf hingewiesen , dass , wenn Ihre Implementierung von tableView:heightForHeaderInSection:Renditen UITableViewAutomaticDimension, dann tableView:viewForHeaderInSection:wird nicht aufgerufen werden.

UITableViewAutomaticDimensionEs wird davon ausgegangen, dass ein Standard verwendet UITableViewHeaderFooterViewwird, der mit der Delegate-Methode gefüllt ist tableView:titleForHeaderInSection:.

Aus Kommentaren in der UITableView.h:

Das Zurückgeben dieses Werts von tableView:heightForHeaderInSection:oder tableView:heightForFooterInSection:führt zu einer Höhe, die dem von zurückgegebenen Wert entspricht tableView:titleForHeaderInSection:oder tableView:titleForFooterInSection:wenn der Titel nicht Null ist.

Benjohn
quelle
1
Wenn Sie einen estimatedSectionHeaderHeightWert festlegen , tableView:viewForHeaderInSectionwird dieser aufgerufen (ähnlich wie die automatischen Abmessungen für Zeilen funktionieren)
GreatWiz
Interessant, danke. Zurück bei 7.1 war diese Subtilität der geschätzten Höhe für Zellen wichtig , so könnte dies auch für Header der Fall gewesen sein - aber sie ist jetzt nicht besonders relevant!
Benjohn
3

Ich hatte gerade ein Problem mit Headern, die für iOS 7.1 nicht angezeigt wurden , aber mit späteren Versionen, die ich getestet habe, einwandfrei funktionieren, explizit mit 8.1 und 8.4.

Für genau denselben Code hat 7.1 überhaupt keine der Delegatmethoden für Abschnittsheader aufgerufen, einschließlich: tableView:heightForHeaderInSection:und tableView:viewForHeaderInSection:.

Nach dem Experimentieren stellte ich fest, dass das Entfernen dieser Zeile aus meinen viewDidLoaderstellten Headern für 7.1 erneut angezeigt wurde und keine Auswirkungen auf andere von mir getestete Versionen hatte:

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

… Also scheint es dort zumindest für 7.1 eine Art Konflikt zu geben.

Benjohn
quelle
3

Das gleiche Problem trat bei mir auf, aber da ich die automatische Höhenberechnung von xCode 9 verwendet habe , kann ich keinen expliziten Höhenwert wie oben angegeben angeben . Nach einigen Experimenten habe ich eine Lösung gefunden , wir müssen diese Methode überschreiben als:

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

Obwohl ich beide Optionen überprüft habe

  1. Automatische Höhenberechnung
  2. Automatische Schätzung der geschätzten Höhe

vom Storyboard, wie Apple sagt, aber trotzdem habe ich diesen seltsamen Fehler.

Bitte beachten Sie : Dieser Fehler wurde nur auf der IOS-10- Version angezeigt, nicht auf der IOS-11- Version. Vielleicht ist es ein Fehler von xCode. Vielen Dank

Najam
quelle
0

Folgendes habe ich gefunden ( Swift 4 ) (dank dieses Kommentars zu einer anderen Frage)

Ob ich titleForHeaderInSection oder viewForHeaderInSection verwendet habe - es war nicht so, dass sie nicht aufgerufen wurden, als die Tabellenansicht gescrollt und neue Zellen geladen wurden, aber alle Schriftarten, die ich für das textLabel der headerView getroffen habe, wurden nur auf dem angezeigt, was beim Laden ursprünglich sichtbar war und nicht, als die Tabelle gescrollt wurde.

Das Update war 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)
    }
}
RanLearns
quelle
0

In meinem Fall habe ich eine Header-Ansicht erstellt, indem ich UITableviewCelldie Zelle viewForHeaderInSectionwie folgt verwendet und zurückgegeben habe

return cell

änderte dies zu

return cell.contentView 

Hat für mich gearbeitet.

user1547608
quelle
0

In meinem Fall

viewForHeaderInSection

wurde in einer weit entfernten abgeleiteten Klasse implementiert, die sich nicht die Mühe machte, in die Oberklasse einzutreten.

Anton Tropashko
quelle
0

Der Grund, warum viewForHeaderInSectionnicht angerufen wird, ist einer von zwei Gründen:

Entweder haben Sie Ihre nicht eingerichtet UITableViewDelegateoder Sie haben Ihre UITableViewDelegatefalsch eingerichtet.

Cem Yilmaz
quelle
0

In meinem Fall war es der Grund, warum ich nicht implementiert habe:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
Nagel Sharipov
quelle
-1

Manchmal kann das Einstellen von tableview.delegateoder datasource = nilin den Methoden viewWillAppear:oder viewDidAppear:dieses Problem verursachen. Stellen Sie sicher, dass Sie dies nicht tun ...

Houzyi
quelle
-1

Ich hatte die folgenden zwei Methoden aus einem Swift 2-Projekt ausgeschnitten und in mein Swift 3-Projekt eingefügt, die nie aufgerufen wurden, da diese Methoden in Swift 3 vor dem ersten Parameternamen "-" haben müssen.

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
}
Koira
quelle