11

Implementé UICollectionView con un diseño personalizado. Agrega una vista de decoración al diseño. Yo uso el siguiente código para agregar atributos de diseño de la decoración de vista:UICollectionView decoración en la vista de colección vacía

-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 
{ 
    NSArray *allAttributes = [super layoutAttributesForElementsInRect:rect]; 
    return [allAttributes arrayByAddingObject:[self layoutAttributesForDecorationViewOfKind:kHeaderKind atIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]]; 
} 

Los datos en la vista de colección se proporciona por un NSFetchedResultsController.

Ahora parecía que funcionaba bien, pero cuando la vista de colección está vacía, falla porque hay una sección 0. Intenté usarla sin una ruta de índice, pero también falla. ¿Alguna idea sobre cómo usar vistas de decoración en un UICollectionView vacío? Debería ser posible ya que las vistas de decoración no están basadas en datos.

+1

Hola, ha resuelto este problema, actualice su respuesta para que también podamos obtener ayuda. –

+0

¿Puede por favor publicar más código para que pueda reproducir el problema fácilmente? –

+1

¿Aparece el mismo mensaje de error en ambos casos? Porque funciona para mí cuando uso 'nil' como ruta de índice (Xcode 5.1.1, iOS SDK 7.1 Simulator). Si falla silenciosamente, tal vez la llamada 'super' devuelva' nil' ('UICollectionViewLayout's default)? –

Respuesta

0

He creado y probado este sencillo ejemplo que parece funcionar en iOS 7 en todas las situaciones posibles (0 secciones, 1 sección con 0 elementos, etc.). Esta es mi clase de diseño, subclase de UICollectionViewFlowLayout. El resto del proyecto es solo andamiaje.

#import "JKLayout.h" 
#import "JKDecoration.h" 

@implementation JKLayout 

- (instancetype)init 
{ 
    if (self = [super init]) { 
     [self registerClass:[JKDecoration class] forDecorationViewOfKind:@"Decoration"]; 
    } 
    return self; 
} 

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 
{ 
    NSArray *allAttributes = [super layoutAttributesForElementsInRect:rect]; 

    // It’s important to set indexPath to nil. If I had set it to indexPath 0-0, it crashed with InternalInconsistencyException 
    // because I was trying to get decoration view for section 0 while there in reality was no section 0 
    // I guess if you need to have several decoration views in this case, you’d identify them with a method other than indexpath 
    return [allAttributes arrayByAddingObject:[self layoutAttributesForDecorationViewOfKind:@"Decoration" atIndexPath:nil]]; 
} 

- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath 
{ 
    UICollectionViewLayoutAttributes *attr = [super layoutAttributesForDecorationViewOfKind:decorationViewKind atIndexPath:indexPath]; 
    if (!attr) { 
     attr = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewKind withIndexPath:indexPath]; 
     attr.frame = CGRectMake(0, 200, 100, 100); 
    } 
    return attr; 
} 

@end 
+1

No estoy seguro si el uso de 'nil' como ruta de índice cambió las cosas, pero con el código anterior funciona perfectamente. También es posible que no funcionara en ese momento, 'UICollectionView's estaba un poco mal en aquel entonces. –

+0

Sí, probablemente una combinación de todo lo anterior. Los documentos no proporcionan mucha orientación acerca de cómo tratar NSIndexPath para vistas de decoración, aparte de decir "Depende de usted decidir cómo usar el parámetro indexPath para identificar una vista de decoración determinada". – Jaanus

+1

Desafortunadamente, esto no funciona más ya que 'layoutAttributesForDecorationViewOfKind: indexPath:' espera una ruta de índice 'nonnull'. – ianolito

4

Cuando se utiliza una vista decoración o una vista suplementario no conectado a una celda específica, usar [NSIndexPath indexPathWithIndex:] para especificar la ruta de índice. Aquí hay un código de muestra:

@interface BBCollectionViewLayout : UICollectionViewFlowLayout 

@end 

@implementation BBCollectionViewLayout 

- (void)BBCollectionViewLayout_commonInit { 
    [self registerClass:[BBCollectionReusableView class] forDecorationViewOfKind:BBCollectionReusableViewKind]; 
} 

- (id)initWithCoder:(NSCoder *)aDecoder { 
    if ((self = [super initWithCoder:aDecoder])) { 
     [self BBCollectionViewLayout_commonInit]; 
    } 
    return self; 
} 

- (id)init { 
    self = [super init]; 
    if (self) { 
     [self BBCollectionViewLayout_commonInit]; 
    } 
    return self; 
} 

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { 
    NSMutableArray *array = [NSMutableArray arrayWithArray:[super layoutAttributesForElementsInRect:rect]]; 

    UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForDecorationViewOfKind:BBCollectionReusableViewKind atIndexPath:[NSIndexPath indexPathWithIndex:0]]; 

    if (CGRectIntersectsRect(rect, attributes.frame)) { 
     [array addObject:attributes]; 
    } 

    return array; 
} 

- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath *)indexPath { 
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:elementKind withIndexPath:indexPath]; 
    attributes.frame = CGRectMake(0., 60., 44., 44.); 
    return attributes; 
} 

@end 
+0

Sí, el uso de NSIndexPath que no se basa en secciones/elementos parece funcionar. Sin embargo, me pone un poco incómodo, creo que la mayoría de estas API asumen que indexPath coincide con el formato de sección de elementos, aunque este uso específico no parece tener ningún efecto negativo. – Jaanus

+0

@Jaanus Si nil fuera un valor aceptable, creo que se mencionaría en la documentación. Es normal no hacer una ruta de índice con un elemento de sección + ya que la ruta de índice no está vinculada a un elemento específico. – Benoit

Cuestiones relacionadas