UITableView: viewForHeaderInSection: não chamado durante reloadData:

127

Eu configurei a tableview com as conexões corretas de delegado e de fonte de dados. O método reloadData chama os métodos de fonte de dados e de delegação, exceto viewForHeaderInSection:.

Por que?

inforeqd
fonte
30
É heightForHeaderInSection:implementado?
7usam
Você definiu um valor para o TableView sectionHeaderHeight?
Carter Medlin

Respostas:

256

O uso de tableView:viewForHeaderInSection:requer que você também implemente tableView:heightForHeaderInSection:. Isso deve retornar uma altura diferente de zero apropriada para o cabeçalho. Verifique também se você não implementou o tableView:titleForHeaderInSection:. Você deve usar apenas um ou outro ( viewForHeaderou titleForHeader).

rmaddy
fonte
3
Verifique se não há um erro de digitação na assinatura do método. Uma letra errada significa que não será chamada. Verifique o caso também. Verifique também se você está retornando 0 de numberOfSections.
Rddydy
tudo está correto e compila corretamente .. o problema que eu queria entender é o momento em que o método é chamado .. tableView: viewForHeaderInSection é chamado quando a tabela está prestes a ser exibida e não como parte da execução da sincronização de [ tableview reloadData]
inforeqd 26/02
@maddy OMG Obrigado, é tão estúpido da minha parte eu criei meus casos, mas não o fiz acréscimo para minha matriz
Happiehappie
4
Você pode absolutamente ter os dois. viewForHeaderInSection: terá precedência sobre titleForHeaderInSection: o único requisito é que você defina o estimado estimadoSectionHeaderHeight na visualização da tabela com algo diferente de 0, caso contrário, viewForHeaderInSection: nunca será chamado
romrom
Adicionando ao comentário do @ romrom: se você implementou os dois titleForHeaderInSection:e viewForHeaderInSection:a exibição retornada deste último é uma subclasse, UITableViewHeaderFooterViewentão ele textLabel.texté automaticamente definido para a versão all-caps da titleForHeaderInSection:string. Para evitar esse comportamento, não implemente titleForHeaderInSection:ou use um rótulo personalizado em vez do herdado textLabel.
Ortwin Gentz ​​21/03
40

O truque é que esses dois métodos pertencem a UITableViewprotocolos diferentes : tableView:titleForHeaderInSection:é um UITableViewDataSourcemétodo de protocolo ao qual tableView:viewForHeaderInSectionpertence UITableViewDelegate.

Que significa:

  • Se você implementar os métodos, mas se atribuir apenas como dataSourcefor UITableView, sua tableView:viewForHeaderInSectionimplementação será ignorada.

  • tableView:viewForHeaderInSectiontem uma prioridade mais alta. Se você implementar ambos os métodos e atribuir-se como tanto o dataSourceeo delegatepara o UITableView, você vai voltar as vistas para cabeçalhos de seção, mas o seu tableView:titleForHeaderInSection:será ignorado.

Eu também tentei remover tableView:heightForHeaderInSection:; funcionou bem e não pareceu afetar os procedimentos acima. Mas a documentação diz que é necessário para tableView:viewForHeaderInSectionque funcione corretamente; para estar seguro, é aconselhável implementar isso também.

Yunus Nedim Mehel
fonte
6
Você fez meu dia!!! Esqueci de atribuir UITableViewDelegatea self, porque eu pensei, que tableView:viewForHeaderInSectioné um UITableViewDataSourcemétodo. Obrigado!
Denis631
1
"tableView: viewForHeaderInSection" não é vital. O que é vital é que, de alguma forma, você retorna uma altura. Você pode conseguir isso através de 1. estimativa ou 2. de um valor codificado ou 3. a titleForHeaderque tenha um tamanho intrínseco. O tamanho intrínseco é calculado com base na família e no tamanho da fonte.
Mel
28

O @rmaddy deturpou a regra duas vezes: na realidade, tableView:viewForHeaderInSection:não é necessário que você também implemente tableView:heightForHeaderInSection:, e também é perfeitamente bom chamar ambos titleForHeadere viewForHeader. Vou declarar a regra corretamente apenas para o registro:

A regra é simplesmente que viewForHeadernão será chamada, a menos que você dê uma altura ao cabeçalho. Você pode fazer isso de qualquer maneira, de três maneiras:

  • Implementar tableView:heightForHeaderInSection:.

  • Coloque as mesas sectionHeaderHeight.

  • Chamada titleForHeader(isso de alguma forma atribui ao cabeçalho uma altura padrão, caso contrário não a possui).

Se você não fizer nada disso, não terá cabeçalhos e viewForHeadernão será chamado. Isso porque, sem altura, o tempo de execução não saberá como redimensionar a exibição, portanto, não se preocupe em pedir uma.

mate
fonte
Dos documentos para tableView:viewForHeaderInSection:: "Este método só funciona corretamente quando tableView:heightForHeaderInSection:também é implementado.".
rmaddy
1
Bem. O que os médicos dizem, eles dizem. Agora experimente. Os fatos são como afirmei.
Matt
E como você pode ter os dois titleForHeaderInSectione viewForHeaderInSection? A exibição da tabela chamará apenas um dos dois (eu esqueço o que tem precedência no momento).
rmaddy
1
Na verdade, há mais uma peça do quebra-cabeça, que às vezes viewForHeader é chamada sem nenhuma dessas três maneiras de atribuir uma altura. Eu tive isso acontecer, onde meu viewForHeaderfoi chamado e os cabeçalhos apareceram muito bem, até que um dia, sem nenhuma alteração da minha parte, eles não o fizeram . Foi quando comecei a experimentar para descobrir como os requisitos mínimos devem viewForHeaderser chamados. E agora eu sei. E agora você também.
matt
2
@texas Não, eu não uso xamarin. Adicionar outro nível de indireção sobre as estruturas de cacau faria minha cabeça explodir. :)
mate
20

Doações estimatedSectionHeaderHeighte sectionHeaderHeightvalores corrigiram meu problema. por exemplo, self.tableView.estimatedSectionHeaderHeight = 100 self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension

Sharukh Mastan
fonte
Meu problema começou após a atualização para o Swift 3.1. Esta solução corrigiu.
zevij 23/05
@pbuchheit O Apple Docs diz que está disponível no iOS 7.0 ou superior, dê uma olhada aqui, developer.apple.com/documentation/uikit/uitableview/…
Sharukh Mastan
@Sharukh Mastan Parece que você está correto. Por algum motivo, recebi um aviso quando tentei usar essa propriedade, mas ela desapareceu após fazer uma compilação limpa.
Pbuchheit
7

Seguindo a resposta de rmaddy, eu estava tentando ocultar a visualização do cabeçalho e retornava 0,0f para "tableView: heightForHeaderInSection" e uma visualização de 0 de altura tableView:viewForHeaderInSection.

Depois de mudar de return 1.0fpara return 0.0fdentro tableView:heightForHeaderInSection, o método delegado tableView:viewForHeaderInSectionfoi realmente chamado.

Acontece que o efeito desejado funciona sem ter que usar "tableView: heightForHeaderInSection"; mas isso pode ser útil para outras pessoas que estão tendo problemas ao obter o método delegado "tableView: heightForHeaderInSection" chamado.

rrrrrraul
fonte
5

Você deve implementar tableView:heightForHeaderInSection:e definir a altura do cabeçalho> 0.

Este método delegado acompanha o viewForHeaderInSection:método.

Eu espero que isso ajude.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
         return 40;
}
Chiara
fonte
Você já testou que sua resposta realmente funciona? Porque se você ler atentamente, é declarado que inicialmente o viewForHeaderInSection é chamado. Não é chamado apenas quando a tabela é recarregada!
Karlis
5

Vale a pena notar brevemente que, se sua implementação de tableView:heightForHeaderInSection:retornos UITableViewAutomaticDimension, tableView:viewForHeaderInSection:não será chamada.

UITableViewAutomaticDimensionpressupõe que UITableViewHeaderFooterViewserá usado um padrão preenchido com o método delegate tableView:titleForHeaderInSection:.

Dos comentários no UITableView.h:

Retornar esse valor de tableView:heightForHeaderInSection:ou tableView:heightForFooterInSection:resultar em uma altura que corresponda ao valor retornado de tableView:titleForHeaderInSection:ou tableView:titleForFooterInSection:se o título não for nulo.

Benjohn
fonte
1
se você definir estimatedSectionHeaderHeighta algum valor, tableView:viewForHeaderInSectionserá chamado (da mesma forma como dimensões de automóveis para linhas funciona)
GreatWiz
Interessante, obrigado. De volta às 7.1, essa sutileza da altura estimada era importante para as células , por isso também poderia ter sido o caso dos cabeçalhos - mas não é muito relevante agora!
21916 Benjohn
3

Acabei de ter um problema com os cabeçalhos que não aparecem no iOS 7.1 , mas funcionando bem com versões posteriores que testei, explicitamente com 8.1 e 8.4.

Para o mesmo código, o 7.1 não estava chamando nenhum dos métodos de delegação do cabeçalho da seção, incluindo: tableView:heightForHeaderInSection:e tableView:viewForHeaderInSection:.

Após a experimentação, descobri que a remoção dessa linha dos viewDidLoadcabeçalhos criados reaparecia no 7.1 e não afetou outras versões que testei:

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

… Então parece que há algum tipo de conflito por 7.1, pelo menos.

Benjohn
fonte
3

O mesmo problema ocorreu comigo, mas como estava usando o cálculo automático de altura do xCode 9 , não posso fornecer nenhum valor explícito de altura, como mencionado acima. Após algumas experiências, obtive a solução , precisamos substituir esse método como,

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

Embora eu tenha marcado as duas opções

  1. Cálculo automático de altura
  2. Cálculo automático de altura estimada

do storyboard como a Apple diz, mas ainda assim recebi esse erro estranho.

Nota : Este erro foi mostrado apenas na versão IOS-10 e não na versão IOS-11 . Talvez seja um bug do xCode. obrigado

Najam
fonte
0

Aqui está o que eu encontrei ( Swift 4 ) (graças a este comentário em outra pergunta)

Se eu usei titleForHeaderInSection ou viewForHeaderInSection - não era que eles não estavam sendo chamados quando a tableview foi rolada e novas células estavam sendo carregadas, mas qualquer opção de fonte que eu fiz para o textLabel do headerView estava aparecendo apenas no inicialmente visível no carregamento , e não como a tabela foi rolada.

A correção foi 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
fonte
0

No meu caso, criei a visualização de cabeçalho usando UITableviewCelle retornando a célula viewForHeaderInSectiondessa maneira

return cell

mudou isso para

return cell.contentView 

Trabalhou para mim.

user1547608
fonte
0

No meu caso

viewForHeaderInSection

foi implementado em uma classe derivada muito distante que não se incomodava em transformar em superclasse.

Anton Tropashko
fonte
0

O motivo pelo qual viewForHeaderInSectionnão é chamado é por um de dois motivos:

Você não configurou o seu UITableViewDelegateou configurou o seu UITableViewDelegateincorretamente.

Cem Yilmaz
fonte
0

No meu caso, foi porque eu não implementei:

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

Às vezes, a configuração tableview.delegateou datasource = nilnos métodos viewWillAppear:ou viewDidAppear:pode causar esse problema. Certifique-se de não fazer isso ...

Houzyi
fonte
-1

Eu recortei e colei os dois métodos a seguir de um projeto Swift 2 no meu projeto Swift 3, que nunca foram chamados, porque no Swift 3 esses métodos devem ter "-" antes do nome do primeiro parâmetro.

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
fonte