UICollectionViewCell usando prototypes de tamaños

Tengo una UICollectionView con tres celdas prototipo diferentes, cada una con diferentes alturas configuradas a través de Storyboard. Durante el time de ejecución, la Vista de Colección utiliza su propio tamaño de celda, ignorando mis Storyboards.

Actualmente estoy usando collectionView: layout: sizeForItemAtIndexPath: con un par de condicionales para establecer cada CGSize recta.

¿Hay una mejor manera de configurar los tamaños de celda? No parece poder recuperar el tamaño de Storyboard que tiene cada celda, y CGSizeMake parece demasiado codificado y no es muy flexible.

Parece que actualmente no hay una manera fácil de:

  • Obtenga el time de ejecución de los tamaños de célula del prototipo UICollectionViewCell de Storyboard (s).
  • Administre tamaños de celdas prototipo en un solo lugar (en lugar de tener que ingresarlas en el prototipo de celda Storyboard e implementar sizeForItemAtIndexPath ).

Un método propuesto aquí (para UITableViews) no funciona, porque usar dequeueReusableCellWithReuseIdentifier en sizeForItemAtIndexPath causará un bucle indefinido.

Sin embargo, he logrado hacer esto de la siguiente manera :

  1. Agregue un identificador de reutilización único (en todos los UICollectionViewCell s en cada storyboard) en cada una de sus UICollectionView prototipo UICollectionView en todos los Storyboards.

  2. Agregue un Run script Build Phase a su proyecto con el script que extrae los tamaños de fotogtwig UICollectionViewCell de todos los Storyboards.

     output=${PROJECT_DIR}/StoryboardPrototypeCellSizes.h printf "@{" > $output for storyboard in $(find ${PROJECT_DIR} -name "*.storyboard") do echo "Scanning storyboard $storyboard..." delimiter= for line in $(xpath $storyboard "//collectionViewCell/@reuseIdentifier[string-length()>0] | //collectionViewCell/rect" 2>&-) do case $line in reuseIdentifier*) reuseIdentifier=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) ;; width*) if [ -n "$reuseIdentifier" ]; then width=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) fi ;; height*) if [ -n "$reuseIdentifier" ]; then height=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) fi ;; esac if [ -n "$reuseIdentifier" ] && [ -n "$width" ] && [ -n "$height" ]; then printf "$delimiter@\"$reuseIdentifier\" : [NSValue valueWithCGSize:CGSizeMake($width, $height)]" >> $output unset reuseIdentifier unset width unset height delimiter=,\\n fi done done printf "};\n" >> $output 

    Esto crea un file de encabezado llamado StoryboardPrototypeCellSizes.h con un contenido de ejemplo siguiente:

     @{@"TodayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 80)], @"SpecialDayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 42)], @"NameDayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 30)]}; 
  3. Agregue un método de ayuda para devolver el identificador de reutilización UICollectionViewCell en el controller de vista que controla su UICollectionView :

     - (NSString *)cellReuseIdentifierAtIndexPath:(NSIndexPath *)indexPath { switch (indexPath.item) { case 0: return @"TodayCell"; case 1: return @"SpecialDayCell"; case 2: return @"NameDayCell"; } return nil; } 
  4. Asegúrese de usar el mismo identificador de reutilización en cellForItemAtIndexPath :

     - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: [self cellReuseIdentifierAtIndexPath:indexPath] forIndexPath:indexPath]; ... 
  5. Finalmente implementa sizeForItemAtIndexPath :

     - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { NSDictionary *storyboardPrototypeCellSizes = #import "StoryboardPrototypeCellSizes.h" return [(NSValue *)storyboardPrototypeCellSizes[ [self cellReuseIdentifierAtIndexPath:indexPath] ] CGSizeValue]; } 

Esta solución le permite definir los tamaños de celda de prototipo de UICollectionViewCell solo una vez en el Storyboard (s) y tampoco realiza ningún cumplimiento de App Store en el time de ejecución.

**** Edición: **** También puede search los tamaños de UICollectionReusableView agregando otro script con el mismo contenido y reemplazando "collectionViewCell" por "collectionReusableView", y cambiando el nombre del file de encabezado por, por ejemplo, StoryboardReusableViewSizes.h

No hay mejor manera de configurar los tamaños de celda. Los tamaños de celda se usan en varios lugares en UICollectionView – para posicionamiento, para indicador de desplazamiento. Y es muy importante recibirlos lo más rápido posible en caso de que el usuario desplace la colección con miles de celdas pequeñas, por ejemplo. Entonces, crear una celda y preguntarle sobre su tamaño no es una opción. Tienes que implementar collectionView: layout: sizeForItemAtIndexPath: y debería funcionar rápidamente.

¿Estás usando el layout de flujo en tu UICollectionView ? En caso afirmativo, puede utilizar el método UICollectionViewDelegateFlowLayout protocolo UICollectionViewDelegateFlowLayout para proporcionar el tamaño de una celda. Si no tiene problemas con los componentes de OSS en su aplicación, RFQuiltLayout se puede usar para lograr esto.