UITableView: viewForHeaderInSection: nie wywołano podczas reloadData:

128

Skonfigurowałem tableview z poprawnymi powiązaniami delegata i źródła danych. Metoda reloadData wywołuje źródło danych i metody delegata, z wyjątkiem metod viewForHeaderInSection:.

Dlaczego to jest takie?

inforeqd
źródło
31
Czy heightForHeaderInSection:wdrożono?
rano
Czy ustawiłeś wartość dla TableView sectionHeaderHeight?
Carter Medlin

Odpowiedzi:

258

Korzystanie z tableView:viewForHeaderInSection:wymagań, które również wdrażasz tableView:heightForHeaderInSection:. Powinno to zwrócić odpowiednią niezerową wysokość nagłówka. Upewnij się również, że nie implementujesz również tableView:titleForHeaderInSection:. Powinieneś używać tylko jednego lub drugiego ( viewForHeaderlub titleForHeader).

rmaddy
źródło
3
Upewnij się, że w podpisie metody nie ma literówki. Jedna zła litera oznacza, że ​​nie zostanie wywołana. Sprawdź też obudowę. Upewnij się również, że zwracasz 0 z numberOfSections.
rmaddy
wszystko jest poprawne i kompiluje się poprawnie. Problem, który chciałem zrozumieć, dotyczy czasu wywołania metody .. tableView: viewForHeaderInSection jest wywoływana, gdy tabela ma zostać wyświetlona, ​​a nie jako część wykonania synchronizacji [ tableview reloadData]
inforeqd
@maddy OMG Dziękuję, to takie głupie z mojej strony, że stworzyłem swoje instancje, ale nie dołączyłem ich do mojej tablicy
Happiehappie
5
Możesz mieć jedno i drugie. viewForHeaderInSection: będzie miał pierwszeństwo przed titleForHeaderInSection: Jedynym wymaganiem jest to, że w widoku tabeli ustawisz wartość ratedSectionHeaderHeight na coś innego niż 0, w przeciwnym razie viewForHeaderInSection: nigdy nie zostanie wywołany
2017
Dodanie do komentarza @ romrom: jeśli zaimplementowałeś oba titleForHeaderInSection:i, viewForHeaderInSection:a widok zwrócony z tego ostatniego jest podklasą, UITableViewHeaderFooterViewto textLabel.textjest automatycznie ustawiany na wersję titleForHeaderInSection:napisu pisaną wielkimi literami . Aby temu zapobiec, nie implementuj titleForHeaderInSection:ani nie używaj etykiety niestandardowej zamiast etykiety dziedziczonej textLabel.
Ortwin Gentz
40

Sztuczka polega na tym, że te dwie metody należą do różnych UITableViewprotokołów: tableView:titleForHeaderInSection:jest to UITableViewDataSourcemetoda protokołu, do której tableView:viewForHeaderInSectionnależy UITableViewDelegate.

To znaczy:

  • Jeśli zaimplementujesz metody, ale przypiszesz siebie tylko jako dataSourcefor UITableView, Twoja tableView:viewForHeaderInSectionimplementacja zostanie zignorowana.

  • tableView:viewForHeaderInSectionma wyższy priorytet. Jeśli zaimplementujesz obie metody i przypiszesz siebie zarówno jako, jak dataSourcei delegatedla UITableView, zwrócisz widoki nagłówków sekcji, ale Twój tableView:titleForHeaderInSection:zostanie zignorowany.

Próbowałem też usunąć tableView:heightForHeaderInSection:; działało dobrze i nie miało wpływu na powyższe procedury. Ale dokumentacja mówi, że jest to wymagane tableView:viewForHeaderInSectiondo prawidłowego działania; więc dla bezpieczeństwa warto to również wdrożyć.

Yunus Nedim Mehel
źródło
6
Zrobiłeś mój dzień !!! Zapomniałem przypisać UITableViewDelegatedo self, bo pomyślałem, że tableView:viewForHeaderInSectionto UITableViewDataSourcemetoda. Dziękuję Ci!
denis631
1
„tableView: viewForHeaderInSection” nie jest istotne. Najważniejsze jest, abyś w jakiś sposób zwrócił wzrost. Możesz to osiągnąć poprzez 1. oszacowanie lub 2. wartość zakodowaną na stałe lub 3. a titleForHeaderktóra ma rozmiar wewnętrzny. Rozmiar wewnętrzny jest obliczany na podstawie rodziny czcionek i rozmiaru.
Miód
28

@rmaddy jest nieprawdziwe regułę, dwukrotnie: w rzeczywistości, tableView:viewForHeaderInSection:czy nie wymagają także wdrożenia tableView:heightForHeaderInSection:, a także jest perfekcyjnie zadzwonić zarówno titleForHeaderi viewForHeader. Prawidłowo podam regułę tylko do protokołu:

Zasada jest taka, viewForHeaderże nie zostanie wywołana, chyba że w jakiś sposób nadasz nagłówkowi wysokość. Możesz to zrobić na trzy sposoby:

  • Wdrażaj tableView:heightForHeaderInSection:.

  • Nakryj do stołu sectionHeaderHeight.

  • Call titleForHeader(to w jakiś sposób nadaje nagłówkowi domyślną wysokość, jeśli w przeciwnym razie nie ma takiej).

Jeśli nie zrobisz żadnej z tych rzeczy, nie będziesz mieć nagłówków i viewForHeadernie zostaniesz wywołany. Dzieje się tak, ponieważ bez wysokości środowisko wykonawcze nie będzie wiedziało, jak zmienić rozmiar widoku, więc nie zawraca sobie głowy pytaniem o jeden.

matowe
źródło
Z dokumentacji dla tableView:viewForHeaderInSection:: „Ta metoda działa poprawnie tylko wtedy, gdy tableView:heightForHeaderInSection:jest również zaimplementowana”.
rmaddy
1
W porządku. Co mówią doktorzy, mówią. Teraz eksperymentuj. Fakty są takie, jak powiedziałem.
mat.
A jak możesz mieć oba titleForHeaderInSectioni viewForHeaderInSection? Widok tabeli wywoła tylko jeden z dwóch (zapominam, który w tej chwili ma pierwszeństwo).
rmaddy
1
W rzeczywistości jest jeszcze jeden element układanki, który czasami viewForHeader jest wywoływany bez żadnego z tych trzech sposobów przypisywania wysokości. Zdarzyło mi się to, że mój viewForHeaderzostał sprawdzony i nagłówki pokazały się dobrze, aż pewnego dnia, bez żadnej zmiany z mojej strony, nie . Wtedy zacząłem eksperymentować, aby odkryć, jakie mają viewForHeaderbyć minimalne wymagania . Teraz już wiem. A teraz ty też.
mat.
2
@texas Nie, nie robię Xamarin. Dodanie kolejnego poziomu pośrednictwa do szkieletów Cocoa po prostu spowodowałoby eksplozję mojej głowy. :)
mat.
20

Dawanie estimatedSectionHeaderHeighti sectionHeaderHeightwartości rozwiązały mój problem. na przykład, self.tableView.estimatedSectionHeaderHeight = 100 self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension

Sharukh Mastan
źródło
Mój problem zaczął się po aktualizacji do Swift 3.1. To rozwiązanie rozwiązało problem.
zevij
@pbuchheit Apple Docs mówi, że jest dostępny od iOS 7.0+, zajrzyj tutaj, developer.apple.com/documentation/uikit/uitableview/…
Sharukh Mastan,
@Sharukh Mastan Wygląda na to, że masz rację. Z jakiegoś powodu otrzymałem ostrzeżenie, kiedy próbowałem użyć tej właściwości, ale zniknęło po wykonaniu czystej kompilacji.
pbuchheit
7

Wychodząc z odpowiedzi rmaddy, próbowałem ukryć widok nagłówka i zwracałem 0,0f dla „tableView: heightForHeaderInSection” i widoku z wysokości 0 tableView:viewForHeaderInSection.

Po zmianie z return 1.0fna return 0.0fin faktycznie tableView:heightForHeaderInSectionwywołano metodę delegata tableView:viewForHeaderInSection.

Okazuje się, że mój pożądany efekt działa bez konieczności używania "tableView: heightForHeaderInSection"; ale może to być przydatne dla innych, którzy mają problem z wywołaniem metody delegata „tableView: heightForHeaderInSection”.

rrrrrraul
źródło
5

Należy zaimplementować tableView:heightForHeaderInSection:i ustawić wysokość nagłówka> 0.

Ta metoda delegata jest zgodna z viewForHeaderInSection:metodą.

Mam nadzieję, że to pomoże.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
         return 40;
}
Chiara
źródło
Czy sprawdziłeś, że Twoja odpowiedź faktycznie działa? Ponieważ ejeśli uważnie czytasz, jest powiedziane, że początkowo wywoływana jest metoda viewForHeaderInSection. Nie jest wywoływana tylko wtedy, gdy stół jest ponownie ładowany!
Karlis
5

Warto krótko zaznaczyć, że jeśli Twoja realizacja tableView:heightForHeaderInSection:zwrotów UITableViewAutomaticDimension, to tableView:viewForHeaderInSection:nie zostanie wywołana.

UITableViewAutomaticDimensionzakłada, że UITableViewHeaderFooterViewzostanie użyty standard wypełniony metodą delegata tableView:titleForHeaderInSection:.

Z komentarzy w UITableView.h:

Zwrócenie tej wartości z tableView:heightForHeaderInSection:lub tableView:heightForFooterInSection:skutkuje wysokością pasującą do wartości zwróconej z tableView:titleForHeaderInSection:lub tableView:titleForFooterInSection:jeśli tytuł nie jest zerowy.

Benjohn
źródło
1
jeśli ustawisz estimatedSectionHeaderHeightjakąś wartość, tableView:viewForHeaderInSectionzostanie wywołany (podobnie jak działa automatyczne wymiary dla wierszy)
GreatWiz
Ciekawe, dzięki. W wersji 7.1 ta subtelność szacowanej wysokości była ważna dla komórek , więc mogła być również w przypadku nagłówków - ale teraz nie jest to szczególnie istotne!
Benjohn,
3

Właśnie miałem problem z nagłówkami, które nie były wyświetlane w iOS 7.1 , ale działały dobrze z późniejszymi wersjami, które testowałem, wyraźnie z 8.1 i 8.4.

Dla dokładnie tego samego kodu 7.1 w ogóle nie wywoływał żadnej z metod delegata nagłówka sekcji, w tym: tableView:heightForHeaderInSection:i tableView:viewForHeaderInSection:.

Po eksperymentach stwierdziłem, że usunięcie tej linii z moich viewDidLoadutworzonych nagłówków pojawia się ponownie w wersji 7.1 i nie ma wpływu na inne wersje, które testowałem:

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

… Więc wydaje się, że jest tam jakiś konflikt, przynajmniej w wersji 7.1.

Benjohn
źródło
3

Ten sam problem wystąpił ze mną, ale ponieważ korzystałem z automatycznego obliczania wysokości z xCode 9 , nie mogę podać żadnej wyraźnej wartości wysokości, jak wspomniano powyżej. Po kilku eksperymentach otrzymałem rozwiązanie , musimy zastąpić tę metodę, ponieważ

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

Chociaż mam zaznaczone obie opcje

  1. Automatyczne obliczanie wysokości
  2. Automatyczne obliczanie szacowanej wysokości

ze scenorysu, jak mówi Apple, ale nadal mam ten dziwny błąd.

Uwaga : ten błąd był wyświetlany tylko w wersji IOS-10, a nie w wersji IOS-11 . Może to błąd z xCode. Dzięki

Najam
źródło
0

Oto, co znalazłem ( Swift 4 ) (dzięki temu komentarzowi do innego pytania)

Czy użyłem titleForHeaderInSection czy viewForHeaderInSection - nie chodziło o to, że nie były wywoływane, gdy przewijano widok tabeli i ładowano nowe komórki, ale wszelkie wybory czcionek, które wybrałem dla textLabel headerView, pojawiały się tylko na tym, co było początkowo widoczne po załadowaniu , a nie podczas przewijania tabeli.

Poprawka to 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
źródło
0

W moim przypadku utworzyłem widok nagłówka, używając UITableviewCelli zwracając komórkę w viewForHeaderInSectionten sposób

return cell

zmieniono to na

return cell.contentView 

Pracował dla mnie.

user1547608
źródło
0

W moim przypadku

viewForHeaderInSection

został zaimplementowany w odległej klasie pochodnej, która nie zawracała sobie głowy stokrotką w superklasie.

Anton Tropashko
źródło
0

Przyczyną viewForHeaderInSectionbraku połączenia jest jeden z dwóch powodów:

Albo nie skonfigurowałeś swojego UITableViewDelegate, albo UITableViewDelegatenieprawidłowo skonfigurowałeś .

Cem Yilmaz
źródło
0

W moim przypadku to dlatego, że nie wdrożyłem:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
Nail Sharipov
źródło
-1

Czasami ustawienie tableview.delegatelub datasource = nilw metodach viewWillAppear:lub viewDidAppear:może powodować ten problem. Upewnij się, że tego nie robisz ...

Houzyi
źródło
-1

Wycinałem i wklejałem następujące dwie metody z projektu Swift 2 do mojego projektu Swift 3, które nigdy nie zostały wywołane, ponieważ w języku Swift 3 te metody muszą mieć znak „-” przed pierwszą nazwą parametru.

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
źródło