Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on data reload with 0 items and sections #76

Closed
natenash203 opened this issue Oct 19, 2014 · 11 comments
Closed

Crash on data reload with 0 items and sections #76

natenash203 opened this issue Oct 19, 2014 · 11 comments

Comments

@natenash203
Copy link

First off, great work on the layout. I use the layout for a couple sections with three or four items each. Each section has a header and the items are populated by data retrieved from a network call. I have a method that removes all objects from the data source and sets everything back to zero. For example, 0 sections, with 0 items. Essentially an empty array. The method looks a bit like this:

- (IBAction)resetButtonTapped:(id)sender
{
    [self.dataSource removeAllObjects];
    [self.collectionView reloadData];
}

Whenever I reset everything back to zero, and call reloadData, the following exception is thrown:

*** Assertion failure in -[UICollectionViewData layoutAttributesForSupplementaryElementOfKind:atIndexPath:], /SourceCache/UIKit_Sim/UIKit-3318/UICollectionViewData.m:853
2014-10-19 19:18:22.554 Hord[31192:4215382] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'request for layout attributes for supplementary view CHTCollectionElementKindSectionHeader in section 0 when there are only 0 sections in the collection view'

A similar issue was reported on another custom UICollectionViewLayout here. However, the other layout appears to have some sort of cache invalidation logic built in.

It looks like the layout object is still trying to return attributes for a header that no longer exists. Any advice you have on resolving this issue is much appreciated. Thanks in advance!

@natenash203
Copy link
Author

As a follow up, I thought I'd share a full example of what I describe in my initial filing. Below is the view controller code. It is based off a storyboard with a UICollectionViewController. Layout object for the UICollectionViewController is set toCHTCollectionViewWaterfallLayout. Two different UIBarButtonItems are connected to the deleteFirstSection and deleteAllSections methods.

#import "GTCollectionViewController.h"

@interface GTCollectionViewController ()

@property (nonatomic, strong) NSMutableArray *dataSource;

@end

@implementation GTCollectionViewController

static NSString * const reuseIdentifier = @"Cell";

- (void)viewDidLoad {
    [super viewDidLoad];

    self.dataSource = [NSMutableArray arrayWithObjects:@{@"sectionName" : @"one",
                                                         @"sectionData": @[@"itemOne", @"itemTwo", @"itemThree"]},
                                                        @{@"sectionName" : @"two",
                                                            @"sectionData": @[@"itemFour", @"itemFive", @"itemSix"]},
                                                        @{@"sectionName" : @"three",
                                                            @"sectionData": @[@"itemSeven", @"itemEight", @"itemNine", @"itemTen"]}, nil];

    CHTCollectionViewWaterfallLayout *waterfall = (CHTCollectionViewWaterfallLayout *)self.collectionViewLayout;

    waterfall.columnCount = 3;

    [self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:CHTCollectionElementKindSectionHeader withReuseIdentifier:@"header"];
}


#pragma mark <UICollectionViewDataSource>

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {

    NSLog(@"Called Sections");
    return self.dataSource.count;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    NSArray *array = self.dataSource[section][@"sectionData"];
    return array.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    NSArray *array = self.dataSource[indexPath.section][@"sectionData"];

    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];

    UILabel *label = (UILabel *)[cell viewWithTag:99];
    label.text = array[indexPath.item];

    cell.contentView.backgroundColor = [UIColor greenColor];

    return cell;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{

    UICollectionReusableView *view;
    if (kind == CHTCollectionElementKindSectionHeader) {
        view = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"header" forIndexPath:indexPath];
        view.backgroundColor = [UIColor redColor];

    }

    return view;
}

#pragma mark - CHTCollectionViewDelegateWaterfallLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(arc4random() % 50 + 50, arc4random() % 50 + 50);
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout heightForHeaderInSection:(NSInteger)section
{
    return 100;
}

- (IBAction)deleteFirstSection:(id)sender
{

    //Will throw exception on last section to be removed

    [self.dataSource removeObjectAtIndex:0];
    [self.collectionView deleteSections:[NSIndexSet indexSetWithIndex:0]];

}

- (IBAction)deleteAllSections:(id)sender
{

    //Will always throw exception

    [self.dataSource removeAllObjects];
    [self.collectionView reloadData];

}
@end

@jhariani
Copy link

I'm experiencing this as well.

@chiahsien
Copy link
Owner

Can anyone fix this issue?
My little boy just delivered so I will not be available for months.
Sorry 😭

@jefflen
Copy link

jefflen commented Feb 24, 2015

I'm experiencing this issue as well, but I solved this by never returns zero in the collection view data source,

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    NSInteger count = [self sectionTitles].count;
    return (count == 0) ? 1 : count;
}

and then check and returns an supplementary view with empty contents,

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
           viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    NSArray *sectionTitles = [self sectionTitles];

    MyCollectionHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind
                                                                            withReuseIdentifier:kind
                                                                                   forIndexPath:indexPath];

    if (sectionTitles.count == 0) {
        headerView.titleLabel.text = @"";
        return headerView;
    }
    else { 
        ...
    }
}

you may need to check for other data source methods as well for this modification.

@chiahsien
Copy link
Owner

Interesting. Can't numberOfSectionsInCollectionView return 0? I can't find any document addressing this, anyone?

@jefflen
Copy link

jefflen commented Feb 24, 2015

I tried to modify the CHTCollectionViewWaterfallLayout class without success so just use this patch method instead. Not sure why it won't works when return zero...

@dginsburg
Copy link
Contributor

Fixed in PR #93

@chiahsien
Copy link
Owner

Thanks @dginsburg !

@hebinda
Copy link

hebinda commented Jan 13, 2016

self.floatingSectionIndex = -1;

Initialization of floatingSectionIndex is needed in prepareLayout. When search result filtered down sections, the current floating section doesn't exist anymore

@Isuru-Nanayakkara
Copy link

I'm getting this error in the Swift version.

@satashiabhavin
Copy link

deinit {
SDWebImageDownloader.shared.cancelAllDownloads()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants