2

I have a UICollectionView which uses a subclass of UICollectionViewCell's. Initially, my dataSource contains 5 items, and when the user scrolls down, I fetch more data and add them to my dataSource, then I call reloadData.

But only 3 items are visible. and when I scroll up I can't see the rest of the items, just an empty area. I noticed that cellForRowAtIndexPath only gets called for those 3 items.

When I navigate to my parent view, and back to the view which contains my UICollectionView I can see all the items.

Note: I have implemented layout:sizeForItemAtIndexPath function as each cell has a different size.

Edit:

I partially solved the issue. I had a refreshControl and I called endRefreshing in a background thread.

Am adding images for a better demonstration of what's happening now:

  • The 1st image is before fetching new data, as u can see the data is displayed perfectly.

enter image description here

  • The 2nd image is after fetching new data, as u can see the new items take the exact height of the previous ones (the old cells) and there is an empty area, when I scroll down I can see the rest of the data, and when I scroll back up, the top cells get the right height, as shown in the 3rd image.

enter image description here

enter image description here

After I finish loading new items, I call this method

- (void)updateDataSource
{
   self.collectionViewDataSource = _manager.messages;
   [self.collectionView reloadData];
}

I checked numberOfItemsInSection method, it returns the right number of items.

and here is my layout:sizeForItemAtIndexPath

- (CGSize)collectionView:(UICollectionView *)collectionView layout:   (UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:  (NSIndexPath *)indexPath 
{
// Here I am calculating the width and height of the textView which will fit the message

SPH_PARAM_List *feed_data=[[SPH_PARAM_List alloc]init];
feed_data=[self.collectionViewDataSource objectAtIndex:indexPath.row];

if ([feed_data.chat_media_type isEqualToString:kSTextByme]||[feed_data.chat_media_type isEqualToString:kSTextByOther])
{

    NSAttributedString *aString = [[NSAttributedString alloc] initWithString:feed_data.chat_message];

    UITextView *calculationView = [[UITextView alloc] init];
    [calculationView setAttributedText:aString];

    [calculationView setFont:[UIFont systemFontOfSize:14]];
    [calculationView setTextAlignment:NSTextAlignmentJustified];


    CGSize sc = [calculationView sizeThatFits:CGSizeMake(TWO_THIRDS_OF_PORTRAIT_WIDTH, CGFLOAT_MAX)];

    NSLog(@"IndexPath: %li Height: %f", (long)indexPath.row ,sc.height);

    return CGSizeMake(self.view.frame.size.width - (5 * 2), sc.height);

}

return CGSizeMake(self.view.frame.size.width - (5 * 2), 90);

}

Edit 2:

I noticed that layout:collectionViewLayoutsizeForItemAtIndexPath: gets called and it returns the right height, but cellForItemAtIndexPath still deals with an old one.

user2037296
  • 409
  • 1
  • 5
  • 13
  • 2
    isn't the method `cellForItemAtIndexPath`? – Schemetrical May 07 '15 at 14:34
  • Update your question with relevant code so we can point out the issue. – rmaddy May 07 '15 at 14:35
  • @rmaddy I have updated my question and added some relevant code, do u need me to add more? – user2037296 May 07 '15 at 17:01
  • Have you attempted to invalidate the layout? Since the top cell needs to be reloaded and resized, you may need to call `[collectionView.collectionViewLayout invalidateLayout];` when the data changes, since the height has to be redetermined for the reused cells – Mike Welsh May 07 '15 at 17:28
  • Just a suggestion: When I see such issues, they are usually caused by not calling UI Kit from the main queue. Make sure you dispatch all calls on the main queue. `dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff` – allprog May 08 '15 at 13:42
  • Did you solve the issue? I am experiencing a similar behavior. – Robert Dec 10 '15 at 17:05
  • Did you solve the issue? I am experiencing a similar issue. – Naveen Shan Nov 18 '16 at 06:39

2 Answers2

1

You likely need to invalidate your layout so that the cell positions and heights get recalculated since simply reloading the data won't properly set the cell heights (since cells are reused).

- (void)updateDataSource
{
   self.collectionViewDataSource = _manager.messages;
   [self.collectionView reloadData];
   // Add this line.
   [self.collectionView.collectionViewLayout invalidateLayout];
}
Mike Welsh
  • 808
  • 5
  • 10
  • nothing changed, unfortunately. :( thanks for the suggestion though. – user2037296 May 08 '15 at 12:37
  • I noticed that collectionView: layout:collectionViewLayout sizeForItemAtIndexPath: gets called and it returns a new height, but cellForItemAtIndexPath still deals with an old height. – user2037296 May 08 '15 at 13:18
  • You aren't changing the layout are you? Just refreshing the cells? What happens if you reload the section (instead of the entire data set) after invalidating the layout? `[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];` ? – Mike Welsh May 08 '15 at 14:14
  • what do u mean by changing the layout? I am just adding new items to my data source, but each item has a different height. I have tried it, and nothing has changed. – user2037296 May 08 '15 at 14:50
  • Based on the images above, it looks like the new data is getting loaded fine. The problem seems to be that the layout doesn't update properly - looks very similar to this question http://stackoverflow.com/questions/13750428/resize-uicollectionview-cells-after-their-data-has-been-set – Mike Welsh May 11 '15 at 12:48
0

Can't figure it out until you show code. However, I guess your data source is not updated. Just check it out, your DataSource should have fetched the data before reloadData. You can put Some log to check number of items before/after reloadData. This might help.

Anni S
  • 1,996
  • 19
  • 28
  • I checked my data source and it's updated. I have added some relevant code. – user2037296 May 07 '15 at 17:02
  • Try performBatchUpdates instead of simple replacing complete list, it'll invalidate layout. This might help. if (//more items to add) { [self.collectionView performBatchUpdates:^{//add items to collection view }]; }else { [self.collectionView reloadData]; } – Anni S May 10 '15 at 11:42