No se llama al método UICollectionReusableView

79

Quiero que mis secciones en el UICollectionViewtengan un encabezado con una imagen.

He seguido estos pasos:

  • en el guión gráfico, asigné un encabezado como accesorio para mi UICollectionView
  • le dio un identificador
  • creó una subclase de UICollectionReusableViewpara ello
  • asignó la clase personalizada a la clase en el guión gráfico.
  • poner un ImageViewaccesorio en el encabezado
  • hizo una salida para la ImageViewclase personalizada en el .harchivo
  • Implementó lo siguiente en viewDidLoad:

 

[self.collectionView registerClass:[ScheduleHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerIdentifier];

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *reusableview = nil;

    if (kind == UICollectionElementKindSectionHeader)
    {
        ScheduleHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerIdentifier forIndexPath:indexPath];

        headerView.headerImageView.image = [UIImage imageNamed:@"blah.png"];

        reusableview = headerView;
    }

    return reusableview;
}

Sé que los métodos de fuente de datos y delegado están funcionando porque puedo ver todas las celdas y sus secciones. Sin embargo, no tengo mis encabezados. Puse un punto de interrupción en el método anterior y nunca se llama.

¿Qué estoy haciendo mal?

Eden V.
fuente
3
Tenga en cuenta que compara los punteros de cadena en kind == UICollectionElementKindSectionHeaderlugar del contenido de las cadenas, probablemente desee utilizar [kind isEqualToString: UICollectionElementKindSectionHeader]en su lugar.
Mac_Cain13

Respuestas:

200

Parece que tienes que darle a tu encabezado un tamaño distinto de cero o collectionView:viewForSupplementaryElementOfKind:atIndexPathno se llama. Entonces, establezca la headerReferenceSizepropiedad del diseño de flujo así:

flowLayout.headerReferenceSize = CGSizeMake(self.collectionView.frame.size.width, 100.f);

Rápido 5+

flowLayout.headerReferenceSize = CGSize(CGSize(width: self.collectionView.frame.size.width, height: 100))

o, impleméntelo collectionView:layout:referenceSizeForHeaderInSectionsi desea variar el tamaño por sección.

rdelmar
fuente
1
en la vista de colección, ¿puedo hacer la altura dinámica mediante el diseño automático en lugar de definir el tamaño de headerReference?
Khant Thu Linn
¿Es posible establecer headerReferenceSize en Storyboard en flowLayout?
Radek Wilczak
1
¡Sí funcionó! layout.headerReferenceSize = CGSize (ancho: (self.collectionView? .frame.width) !, alto: 50); para swift4
Antony Ouseph
headerReferenceSizefunciona pero necesito diferentes tamaños para diferentes secciones. Y el método que especificó no se llama en absoluto
Vyachaslav Gerchicov
33

Respondiste la pregunta, pero con palabras entiendo mejor:

Para hacer que se llame al método, agregue estos métodos:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section {
    return CGSizeMake(60.0f, 30.0f);
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section {
    return CGSizeMake(60.0f, 30.0f);
}

... y partir de ahí.

Pera Johan
fuente
31

Swift 4 Xcode 9.1 Beta 2

Agregar @objc

@objc func collectionView(_ collectionView: UICollectionView, layout  collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize{
    let size = CGSize(width: 400, height: 50)
    return size
}

Créditos: https://medium.com/@zonble/your-delegation-methods-might-not-be-called-in-swift-3-c6065ed7b4cd

cwilliamsz
fuente
¡Gracias! Salvó mi trasero. Por cierto, noté que esta función no aparece en la lista de autocompletar para collectionViewDelegate. No sé por qué, tan raro. También es extraño que necesitemos la etiqueta @objc delante.
C0D3
3
Solo agregar @objc a la función en Swift 4 funcionó para mí. Ridículo.
Louis Cremen
7
El cumplimiento de UICollectionViewDelegateFlowLayout en lugar de UICollectionViewDelegate también corrige esto sin @objc si está utilizando UICollectionViewFlowLayout.
nemissm
es mucho mejor si usa los límites de collectionView para establecer el encabezado / pie de página de su sección: let size = CGSize (collectionView.bounds.width, height: 50)
omaestra
18

¿Agregó UICollectionViewDelegateFlowLayout en la interfaz actual? Esto funcionó para mí.

@interface MyViewController () <UICollectionViewDelegateFlowLayout>

Rápido:

class MyViewController: UICollectionViewDelegateFlowLayout {

CheshireKat
fuente
1
¡Ahh! así que esto es todo ...UICollectionViewDelegateFlowLayout
Ayan Sengupta
8

Swift 3.0 (xcode 8.2.1)

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    return CGSize(width:collectionView.frame.size.width, height:30.0)
}
Zeeshan
fuente
5

Existe la versión rápida:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    let size = CGSize(width: 400, height: 50)
    return size
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
    let size = CGSize(width: 400, height: 50)
    return size
}

¡XCode (versión 7.3.1) no propone estos métodos en autocompletar!

Si solo desea un encabezado, mantenga el método del encabezado.

Kevin ABRIOUX
fuente
3
    @objc (collectionView:viewForSupplementaryElementOfKind:atIndexPath:)
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { }

El código anterior funcionó para mí

Bibin Jaimon
fuente
2

Mi problema fue que en Swift 3, el nombre de la función viewForSupplementaryElementOfKind ha cambiado ligeramente de cualquier publicación que estuviera en desbordamiento de pila. Por lo tanto, nunca fue llamado. Asegúrese de que, si está en swift 3, su función delegada coincide:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {}
Daniel Jones
fuente
Mío también. Para mí, faltaban "_", "atIndexPath" en lugar de "at" y "NSIndexPath" en lugar de "IndexPath"; ya que he copiado el método de algún lugar y el IDE no me dio un error.
Ashkan Sarlak
1

Tengo el mismo problema. He agregado, referenceSizeForFooterInSectionpero tampoco viewForSupplementaryElementOfKindme llaman. He agregado este código viewDidLoad()y funcionó para mí:

if let flowLayout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
    flowLayout.sectionFootersPinToVisibleBounds = true   
}
Centelleo
fuente
0

Para mí, en Swift 4.2, nunca se llamó a func collectionView (collectionView: kind: indexPath :) -> UICollectionReusableView. Esto fue para una vista de colección en un UIViewController. Noté que las funciones de vista de colección existentes estaban calificadas con @objc, y que UICollectionView no había adoptado los protocolos UICollectionViewDataSource y UICollectionViewDelegate. Tan pronto como adopté los protocolos, recibí errores de que las funciones de vista de colección no coincidían con el protocolo. Corrigí la sintaxis de la función, eliminé los calificadores y los encabezados de las secciones comenzaron a funcionar.

trishcode
fuente
0

Si tiene una subclase genérica, debe tener cuidado de especificar el nombre del método delegado de ObjC si es diferente al nombre de Swift ( https://bugs.swift.org/browse/SR-2817 ).

@objc (collectionView:viewForSupplementaryElementOfKind:atIndexPath:)
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
...
Adrian Bilescu
fuente