11

Я внедрил UICollectionView с пользовательским макетом. Он добавляет украшение в макет. Я использую следующий код для добавления макета атрибутов вида декорирования:UICollectionView украшение в пустом виде коллекции

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

Данные в целях сбора обеспечивается NSFetchedResultsController.

Теперь он выглядел так, как будто он работал нормально, но когда вид коллекции пуст, он терпит неудачу, потому что есть раздел 0. Пытался использовать его без указательного пути, но тоже не удалось. Любые мысли о том, как использовать вид декора в пустом UICollectionView? Должно быть возможным, так как декорации не управляются данными.

+1

Привет, вы решили эту проблему, пожалуйста, обновите свой ответ, чтобы мы также могли получить некоторую помощь. –

+0

Можете ли вы отправить еще какой-нибудь код, чтобы я мог легко воспроизвести проблему. –

+1

Получаете ли вы такое же сообщение об ошибке в обоих случаях? Потому что он работает для меня, когда я использую 'nil' в качестве указательного пути (Xcode 5.1.1, iOS SDK 7.1 Simulator). Если это не так, вместо этого, возможно, вызов 'super' возвращает' nil' ('UICollectionViewLayout' по умолчанию)? –

ответ

0

Я создал и протестировал этот простой пример, который, кажется, работает в iOS 7 во всех возможных ситуациях (0 секций, 1 секция с 0 элементами и т. Д.). Это мой класс макета, подкласс UICollectionViewFlowLayout. Остальная часть проекта - просто строительные леса.

#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

Не уверен, что использование «nil» в качестве указательного пути изменило ситуацию, но с кодом выше он отлично работает. Возможно также, что тогда это не сработало, 'UICollectionView' s были некорректными. –

+0

Да, возможно, комбинация всех вышеперечисленных. Документы не дают большого указания о том, как рассматривать NSIndexPath для оформления видов, кроме как сказать: «Вам решать, как использовать параметр indexPath для идентификации данного вида декора». – Jaanus

+1

К сожалению, это больше не работает, так как 'layoutAttributesForDecorationViewOfKind: indexPath:' ожидает указательный путь 'nonnull'. – ianolito

4

При использовании вида декорирования или дополнительный вид не прилагается к конкретной ячейке, используйте [NSIndexPath indexPathWithIndex:] указать путь индекса. Вот пример кода:

@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

Да, используя NSIndexPath, который не основан на разделах/элементах, похоже, работает. Мне кажется, мне немного неудобно - я думаю, что большинство из этих API-интерфейсов предполагают, что indexPath соответствует формату section.item, хотя это конкретное использование, похоже, не имеет каких-либо негативных последствий. – Jaanus

+0

@Jaanus Если значение nil было приемлемым, я думаю, что это будет упомянуто в документации. Нормально не создавать индексный путь с элементом section +, поскольку путь указателя не привязан к определенному элементу. – Benoit