Search code examples
iosipadios7

UICollectionView refresh data


I am using a CollectionView which displays an array of objects. On clicking a button i fill this array with a new set of data. I want to refresh the CollectionView with this data. Is there any statement to update this instead of comparing each items and selectively deleting and adding? The reloadData usually ends up in the following error.

CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION

In Short, I am looking for the following steps... 1)Fill the datasource array, show the data. 2)Fill the datasource array with new data, refresh the CollectionView to show the data.

Thanks in Advance


Solution

  • Try - (void)performBatchUpdates:(void (^)(void))updates completion:(void (^)(BOOL finished))completion.

    In your case, you want "an all new set of data", so to speak, so e.g:

    [myCV performBatchUpdates:^{
        // one of:
        // a)
        [myCV deleteSection:someIndexSetForTheEntireSection];
        [myRealDataSource empty:someIndexSetForTheEntireSection];
        //
        // OR b)
        [myCV deleteItemsAtIndexPaths:someSetOfIndexPaths];
        [myRealDataSource removeIndexPaths:someSetOfIndexPaths];
    
        // Either case:
        NSArray *indexPaths = [myRealDataSource getNewDataAndReturnIndexPaths];
    
        // if a)
        [myCV insertSections:newIndexSetForNewSection];
    
        // Either case:
        [myCV insertItemsAtIndexPaths:newIndexSetForInsertions];
    }
    completion:^(BOOL finished) {
        NSLog(@"Done.");
        // Maybe signal something else if you want.
    }];
    

    performBatchUpdates:completion: will expect the deletions & insertions from the original data source check entering the function to add up to the correct data source size leaving the method. It will loudly complain otherwise.

    If you only have one section (section 0), you can be much more general than specific index paths if you are always "removing everything" and "inserting a complete new set".

    Another option to to use KVO to listen on insertions and removals from the data source and simply reloadData, reloadItemsAtIndexPaths: or reloadSections: as appropriate.

    I prefer the reactive KVO version, as I tend to use collection views with Core Data, and not pseudo-static or in-memory NSArray's.

    To figure out the CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION issue, I'd setup a breakpoint on all exceptions, and try to discover what is really triggering the issue. Likely your datasource is gone and there's a bad access when you try to read/write from it.