UITableView: viewForHeaderInSection: no llamado durante reloadData:

127

He configurado la vista de tabla con los enlaces correctos de delegado y fuente de datos. El método reloadData llama a la fuente de datos y los métodos delegado a excepción de viewForHeaderInSection:.

¿Por qué es así?

inforeqd
fuente
30
¿Está heightForHeaderInSection:implementado?
7 de
¿Ha establecido un valor para TableView's sectionHeaderHeight?
Carter Medlin

Respuestas:

256

El uso de tableView:viewForHeaderInSection:requiere que también implemente tableView:heightForHeaderInSection:. Esto debería devolver una altura distinta de cero para el encabezado. También asegúrese de no implementar también el tableView:titleForHeaderInSection:. Solo debe usar uno u otro ( viewForHeadero titleForHeader).

rmaddy
fuente
3
Asegúrese de que no haya un error tipográfico en la firma del método. Una letra incorrecta significará que no se llamará. Revise el caso también. También asegúrese de que está devolviendo 0 desde numberOfSections.
rmaddy
todo es correcto y se compila correctamente ... el problema que quería entender es el momento en que se llama al método .. tableView: viewForHeaderInSection se llama cuando la tabla está a punto de mostrarse y no como parte de la ejecución de sincronización de [ tableview reloadData]
inforeqd
@maddy OMG Gracias, es tan estúpido de mi parte que creé mis instancias pero no agregué a mi matriz
Happiehappie
44
Absolutamente puedes tener ambos. viewForHeaderInSection: tendrá prioridad sobre titleForHeaderInSection: el único requisito es que establezca estimadoSectionHeaderHeight en su vista de tabla con algo diferente a 0; de lo contrario, viewForHeaderInSection: nunca se llamará
desde
Agregando al comentario de @ romrom: si ha implementado ambos titleForHeaderInSection:y viewForHeaderInSection:la vista devuelta por este último es una subclase de, UITableViewHeaderFooterViewentonces textLabel.textse establece automáticamente en la versión en mayúsculas de la titleForHeaderInSection:cadena. Para evitar este comportamiento, no implemente titleForHeaderInSection:ni use una etiqueta personalizada en lugar de la heredada textLabel.
Ortwin Gentz
40

El truco es que esos dos métodos pertenecen a UITableViewprotocolos diferentes : tableView:titleForHeaderInSection:es un UITableViewDataSourcemétodo de protocolo, al que tableView:viewForHeaderInSectionpertenece UITableViewDelegate.

Eso significa:

  • Si implementa los métodos pero se asigna solo como dataSourcepara UITableView, su tableView:viewForHeaderInSectionimplementación será ignorada.

  • tableView:viewForHeaderInSectionTiene una mayor prioridad. Si implementa ambos métodos y se asigna a sí mismo como el dataSourcey delegatepara el UITableView, devolverá las vistas para los encabezados de sección, pero tableView:titleForHeaderInSection:se ignorará.

También he intentado eliminar tableView:heightForHeaderInSection:; funcionó bien y no pareció afectar los procedimientos anteriores. Pero la documentación dice que es necesario para tableView:viewForHeaderInSectionque funcione correctamente; así que para estar seguros, es aconsejable implementar esto también.

Yunus Nedim Mehel
fuente
66
¡¡¡Me has alegrado el día!!! Se olvidó de asignar UITableViewDelegatea self, porque pensé, que tableView:viewForHeaderInSectiones un UITableViewDataSourcemétodo. ¡Gracias!
denis631
1
"tableView: viewForHeaderInSection" no es vital. Lo que es vital es que de alguna manera devuelves una altura. Puede lograrlo a través de 1. estimación o 2. un valor codificado o 3. a titleForHeaderque tiene un tamaño intrínseco. El tamaño intrínseco se calcula en función de la familia de fuentes y el tamaño.
Miel
28

@rmaddy ha tergiversado la regla, en dos ocasiones: en realidad, tableView:viewForHeaderInSection:no no requieren que se implemente también tableView:heightForHeaderInSection:, y también está perfectamente bien para llamar tanto titleForHeadery viewForHeader. Declararé la regla correctamente solo para el registro:

La regla es simplemente que viewForHeaderno se llamará a menos que de alguna manera le des una altura al encabezado. Puede hacer esto en cualquier combinación de tres formas:

  • Poner en práctica tableView:heightForHeaderInSection:.

  • Poner la mesa sectionHeaderHeight.

  • Llamada titleForHeader(esto de alguna manera le da al encabezado una altura predeterminada si de lo contrario no tiene uno).

Si no hace ninguna de esas cosas, no tendrá encabezados y viewForHeaderno se le llamará. Eso es porque sin una altura, el tiempo de ejecución no sabrá cómo cambiar el tamaño de la vista, por lo que no se molesta en pedir una.

mate
fuente
De los documentos para tableView:viewForHeaderInSection:: "Este método solo funciona correctamente cuando tableView:heightForHeaderInSection:también se implementa".
rmaddy
1
Multa. Lo que dicen los documentos, dicen. Ahora experimenta. Los hechos son como he dicho.
mate
¿Y cómo puedes tener ambas titleForHeaderInSectiony viewForHeaderInSection? La vista de tabla solo llamará a uno de los dos (se me olvida cuál tiene prioridad en este momento).
rmaddy
1
En realidad, hay una pieza más del rompecabezas, que a veces viewForHeader se llama sin ninguna de esas tres formas de asignar una altura. Me ha sucedido esto, donde me viewForHeaderllamaron y los encabezados aparecieron muy bien, hasta que un día, sin cambios de mi parte, no lo hicieron . Fue entonces cuando comencé a experimentar para descubrir cuáles son los requisitos mínimos para viewForHeaderser llamado. Y ahora lo se. Y ahora tú también.
mate
2
@texas No, no hago xamarin. Agregar otro nivel de indirección en la parte superior de los marcos de Cocoa me haría explotar la cabeza. :)
mate
20

Dar estimatedSectionHeaderHeighty los sectionHeaderHeightvalores arreglaron mi problema. p.ej, self.tableView.estimatedSectionHeaderHeight = 100 self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension

Sharukh Mastan
fuente
Mi problema comenzó después de actualizar a Swift 3.1. Esta solución lo solucionó.
zevij
@pbuchheit Apple Docs dice que está disponible desde iOS 7.0+, eche un vistazo aquí, developer.apple.com/documentation/uikit/uitableview/…
Sharukh Mastan
@Sharukh Mastan Parece que tienes razón. Por alguna razón recibí una advertencia cuando intenté usar esa propiedad, pero desapareció después de hacer una compilación limpia.
pbuchheit
7

Saliendo de la respuesta de rmaddy, estaba tratando de ocultar la vista de encabezado y estaba volviendo 0.0f para "tableView: heightForHeaderInSection" y una vista de altura 0 desde tableView:viewForHeaderInSection.

Después de cambiar de return 1.0fa return 0.0fin tableView:heightForHeaderInSection, el método delegado tableView:viewForHeaderInSectionfue llamado.

Resulta que mi efecto deseado funciona sin tener que usar "tableView: heightForHeaderInSection"; pero esto puede ser útil para otras personas que tienen problemas para obtener el método de delegado "tableView: heightForHeaderInSection" llamado.

rrrrrraul
fuente
5

Debe implementar tableView:heightForHeaderInSection:y establecer la altura para el encabezado> 0.

Este método delegado va junto con el viewForHeaderInSection:método.

Espero que esto ayude.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
         return 40;
}
Chiara
fuente
¿Has probado que tu respuesta realmente funciona? Si lees detenidamente, se dice que inicialmente se llama a viewForHeaderInSection. ¡No se llama solo cuando se recarga la tabla!
Karlis
5

Vale la pena señalar brevemente que si su implementación de tableView:heightForHeaderInSection:devoluciones UITableViewAutomaticDimension, tableView:viewForHeaderInSection:no se llamará.

UITableViewAutomaticDimensionasume que se UITableViewHeaderFooterViewusará un estándar que se rellena con el método delegado tableView:titleForHeaderInSection:.

De los comentarios en UITableView.h:

Si se devuelve este valor tableView:heightForHeaderInSection:o se tableView:heightForFooterInSection:obtiene una altura que se ajusta al valor devuelto tableView:titleForHeaderInSection:o tableView:titleForFooterInSection:si el título no es nulo.

Benjohn
fuente
1
si establece estimatedSectionHeaderHeightalgún valor, tableView:viewForHeaderInSectionse llamará (de forma similar a cómo funcionan las dimensiones automáticas para filas)
GreatWiz
Interesante, gracias. De vuelta en 7.1, esta sutileza de altura estimada era importante para las celdas , por lo que también podría haber sido el caso de los encabezados, ¡pero ahora no es tan relevante!
Benjohn
3

Acabo de tener un problema con los encabezados que no se muestran para iOS 7.1 , pero funcionan bien con versiones posteriores que he probado, explícitamente con 8.1 y 8.4.

Para el mismo código exacto, 7.1 no estaba llamando a ninguno de los métodos de delegado de encabezado de sección, incluidos: tableView:heightForHeaderInSection:y tableView:viewForHeaderInSection:.

Después de experimentar, descubrí que la eliminación de esta línea de mis viewDidLoadencabezados hechos vuelve a aparecer para 7.1 y no afectaba a otras versiones que probé:

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

... entonces, parece que hay algún tipo de conflicto allí para 7.1, al menos.

Benjohn
fuente
3

El mismo problema ocurrió conmigo, pero como estaba usando el cálculo automático de altura de xCode 9 , no puedo dar ningún valor de altura explícito como se mencionó anteriormente. Después de experimentar un poco, obtuve una solución , tenemos que anular este método ya que,

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

Aunque he marcado ambas opciones

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

del guión gráfico como dice apple, pero aún así recibí este extraño error.

Nota : este error se mostró solo en la versión IOS-10 , no en la versión IOS-11 . Tal vez es un error de xCode. Gracias

Najam
fuente
0

Esto es lo que he encontrado ( Swift 4 ) (gracias a este comentario en otra pregunta)

Si utilicé titleForHeaderInSection o viewForHeaderInSection, no era que no se les llamara cuando se desplazaba la vista de tabla y se cargaban nuevas celdas, sino que las opciones de fuente que hice para la etiqueta textView de headerView solo aparecían en lo que inicialmente era visible en la carga , y no como se desplazaba la mesa.

La solución fue 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
fuente
0

En mi caso, he creado una vista de encabezado usando UITableviewCelly devolviendo la celda de viewForHeaderInSectionesta manera

return cell

cambió esto a

return cell.contentView 

Trabajó para mi.

usuario1547608
fuente
0

En mi caso

viewForHeaderInSection

se implementó en una clase derivada muy lejana que no se molestaba en convertirse en superclase.

Anton Tropashko
fuente
0

La razón por la viewForHeaderInSectionque no se llama es por una de dos razones:

O no configuró su UITableViewDelegate, o configuró su UITableViewDelegateincorrectamente.

Cem Yilmaz
fuente
0

En mi caso fue porque no implementé:

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

A veces, configurar tableview.delegateo datasource = nilen los métodos viewWillAppear:o viewDidAppear:puede causar este problema. Asegúrate de no hacer esto ...

Houzyi
fuente
-1

Había cortado y pegado los siguientes dos métodos de un proyecto Swift 2 en mi proyecto Swift 3 que nunca se llamaron porque en Swift 3 estos métodos deben tener "-" antes del primer nombre del 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
fuente