CollectionView sizeForItemAtIndexPath nunca llamado

94

¡Esto me está volviendo loco! Tengo un UICollectionViewController como se muestra a continuación:

class PhrasesCompactCollectionViewController: UICollectionViewController

Se llama a numberOfSections y cellForItemAt, pero nunca se llama a sizeForItemAtIndexPath. Estoy usando el mismo código exacto en otro lugar y se dispara correctamente. Estoy usando Xcode 8 Beta 6.

func collectionView(collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAtIndexPath indexPath:  NSIndexPath) -> CGSize {

        return CGSize(width: 120, height:120) 
    }
john doe
fuente

Respuestas:

251

Debe especificar que implementa el protocolo UICollectionViewDelegateFlowLayouten su declaración de clase.

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout

almas
fuente
10
Hice esto pero todavía no se llama. :(
Van Du Tran
57

En Swift 3+ use este método:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width:(collectionView.frame.height-90)/2, height: 100)
}

Asegúrese de que su clase cumpla tanto Delegar

  • UICollectionViewDelegate

  • UICollectionViewDelegateFlowLayout

Shiv Kumar
fuente
4
Es redundante cumplir con lo UICollectionViewDelegateque ya hace UICollectionViewController.
Van Du Tran
3
@VanDuTran No es redundante afirmar que es obligatorio porque no es necesario ser un UICollectionViewController ...
Michael Hudson
Creo que quiso decir que una vista que no es de colección, Viewcontroller puede ser UICollectionViewDelegate.
ScottyBlades
1
UICollectionViewDelegateFlowLayout hereda de UICollectionViewDelegate, así que simplemente implemente UICollectionViewDelegateFlowLayout
evya
47

Yo tuve el mismo problema. Lo único que me ayudó fue hacer el 'Tamaño estimado' para el Tamaño de celda en el inspector de tamaño de collectionView 'Ninguno'.

ingrese la descripción de la imagen aquí

Zenman C
fuente
9
Me salvaste el día amigo, eres un héroe
Asif Ali
1
De alguna manera, todas las demás respuestas en todas las demás publicaciones sobre el uso sizeForItemAtno mencionaron esto. Muy útil.
JCutting8
¡¡¡¡Esto es Loco!!!! Probé en el simulador de iPhone 5 con la versión 10.3.1 de iOS y se llamó al método. en el simulador de iPhone 5s con el método de la versión 10.3.1 no se llama !!! Cambié el Tamaño estimado a Ninguno. Comenzó a recibir llamadas en iPhone 5s. WT WT WT
hasan
¡Muchas gracias! Mi vista de colección con la costumbre sizeForItemAtfuncionó bien hasta Xcode 11.4 cuando de repente las celdas tenían un ancho incorrecto. Probé un montón de cosas y finalmente funcionó.
Filip
Me salvaste el tiempo. Muchas gracias.
Shahbaz Akram
15

Swift 3

Para establecer el tamaño de celda de UICollectionView, debe crear y personalizar el objeto UICollectionViewFlowLayout. Personalice las propiedades y establezca ese objeto de diseño en el objeto UICollectionView.

Cambie los objetos cellheight y cell cellWidth según sus requisitos (la altura y el ancho de celda que desee).

override func viewDidLoad() {
    super.viewDidLoad()

    let cellWidth : CGFloat = myCollectionView.frame.size.width / 4.0
    let cellheight : CGFloat = myCollectionView.frame.size.height - 2.0
    let cellSize = CGSize(width: cellWidth , height:cellheight)

    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical //.horizontal
    layout.itemSize = cellSize
    layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
    layout.minimumLineSpacing = 1.0
    layout.minimumInteritemSpacing = 1.0
    myCollectionView.setCollectionViewLayout(layout, animated: true)

    myCollectionView.reloadData()
}

Asegúrese: si agregó el método sizeForItemAt indexPath, entonces debe ELIMINAR el método ...

Eliminar método a continuación

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

}
Gaurav Rami
fuente
12
¿Cómo es esto útil?
almas
1
Almas, esto será útil para establecer el tamaño de celda personalizado de UICollectionViewCell ... Hay variables cellWidth y cellHeight, en las que puede definir sus propios valores ... Así como "layout.sectionInset", "layout.minimumLineSpacing" y "layout .minimumInteritemSpacing ", estas variables también son importantes para el tamaño de UICollectionViewCell ..
Gaurav Rami
2
Esto solo funciona si todas las celdas tienen el mismo tamaño. La siguiente respuesta es la respuesta correcta
JeffN
esto es para cambiar el tamaño de UICollectionView pero no la celda dentro de la vista
Async-
Esta no es una respuesta a por qué no se llama al método de delegado
Ziv Kesten
12

Rápido 5

Todos estos pasos son obligatorios :

  1. Conforme a UICollectionViewDelegateFlowLayout <== ¡¡Absolutamente necesario !!
  2. y para UICollectionViewDelegate, UICollectionViewDataSource
  3. Establecer estos en viewDidLoad: collectionView.delegate = selfycollectionView.dataSource = self
  4. Establecer tamaño estimado en Ninguno en el generador de interfaces
  5. Asegúrese de que el siguiente método tenga sizeForItemAt y no sizeForItemAtIndexPath

como :

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
    return CGSize(width: 100, height:100)
} 
Xys
fuente
2
Estimar el tamaño a Ninguno: ¡salve mi día!
Joe Hallenbeck
6

La primera clase necesita confirmar con UICollectionViewDelegateFlowLayout. Entonces necesitas escribir el siguiente código en viewDidLoad ():

// Para decirle a UICollectionView que use los métodos UICollectionViewDelegateFlowLayout de su UIViewController

collectionView.delegate = self

// Si desea configurar su propio diseño de flujo de vista de colección

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //depending upon direction of collection view

self.collectionView?.setCollectionViewLayout(layout, animated: true)

Al usar este código, método UICollectionViewDelegateFlowLayout

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize

se llamará, puede establecer el tamaño en este método.

HS Progr
fuente
4

Tres cosas que debe verificar si ninguna respuesta funciona:

  1. Implementar el delegado de FlowLayout: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. Utilice el método para el tamaño del artículo para swift 3.0+: func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: (collectionView.frame.width / 3) - 1, height: collectionView.frame.width) }

  3. Seleccione Estimate size = Noneen Inspeccionar elemento de UICollectionView.

Manish
fuente
2

Tuve el mismo problema y nada lo solucionaría. Tenía una advertencia amarilla que decía que lo hiciera privado porque se acercaba a otra función definida por el Delegado de diseño. Lo que me arregló fue:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize

Observe la diferencia entre "sizeForItemAtIndexPath" y el "sizeForItemAt" correcto.

Me arranqué el pelo durante días tratando de resolver esto y finalmente funcionó. A continuación, incluiré todas mis funciones para mostrarles cómo también "escondí" una celda haciendo que la altura fuera igual a 0.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let findIndex = labelArray.index(of: "\(labelArray[indexPath.row])")
    let screenSize = UIScreen.main.bounds
    let screenWidth = screenSize.width

    if (findIndex! % 2 == 0){
        // Even index, show cell
        return CGSize(width: screenWidth, height: 246)
    }
    else {
        return CGSize(width: screenWidth, height: 0)
    }
}
Stephen Rains
fuente
0

Tuve este problema anoche. Finalmente lo resolví a la medianoche cuando me di cuenta de que el método 'didSelectItemAtIndex' no estaba cerrado con un corchete de cierre "}"

Agregué un corchete de cierre en la parte inferior de la clase cuando me preguntó por el error de compilación. Entonces, en efecto, todos los métodos debajo de 'didSelectItemAtIndex' estaban dentro de ese método.

Publicando aquí solo en caso de que alguien más pierda 4 horas de sus tardes en este :-(

Charlie Seligman
fuente
0

Asegúrese de poner esto en viewDidLoad ()

collectionView.delegate = self
Azam
fuente
0

mi problema era que tenía mi objeto UICollectionViewDataSource creado como variable local. Entonces, si inicializa su objeto dataSource manualmente en código, asegúrese de almacenarlo como variable global.

Petro Darchyn
fuente
0

Usa este método

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

}

En vez de

private func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

}
Abdul Malik Aman
fuente
0

Simplemente agregue: UICollectionViewDelegateFlowLayout

class YourClass: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {}
Muzammil
fuente
-11

Para mí (en Swift 3.1) el método debe declararse público de esta manera:

    public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
       return CGSize()
    }

No olvide hacerlo público .

Oliver Eichhorn
fuente
publices lo que usa para hacer que su código sea accesible entre marcos y módulos.
ScottyBlades