5

I am trying to get lazy-loading like behavior from my NSCollectionView. (honestly I assumed it had it, like a UITableView - seems like an obvious omission?)

Anyway, I am displaying images in the cells, and would like to load images as they are about to scroll into view, and unload them after they leave.

This is for a research tool and does not need to be pretty - ie: stuff can "pop" in.

Any ideas? My first thought is to find some way for the Views in the collection to know when they're onscreen, but drawrect seems to be called many many times, far more times than there are views on screen.

user441669
  • 1,054
  • 1
  • 10
  • 23

1 Answers1

7

As you mention, NScollectionView builds all cells at once. Specially if there are lots of images inside cells that cause performance issues. This is how I solve the problem. There might be a better solutions but as far as this is working fine for me. For a long time I have observed performance of the code with Instruments and did not see any down side.

- (void)windowDidLoad {
    //Here adding observer to NSCollectionView's scrollview to monitor bounds changes.
    NSView *contentView = [scrollViewOfYourCollectionView contentView];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(boundDidChange:) name:NSViewBoundsDidChangeNotification object:contentView];
}

- (void)boundDidChange:(NSNotification *)notification
{
    NSRect collectionViewVisibleRect = yourCollectionView.visibleRect;
    //collectionViewVisibleRect.size.height += 300; //If you want some preloading for lower cells...

    for (int i = 0; i < yourDataSourceArray.count; i++) {
         NSCollectionItem *item = [yourCollectionView itemAtIndex:i];
         if (NSPointInRect(NSMakePoint(item.view.frame.origin.x, item.view.frame.origin.y), collectionViewVisibleRect) == YES)
         {
             if (item.imageView.image == nil) {
                 dispatch_async(dispatch_get_main_queue(), ^{
                 //Fill your cells. 
                 //to showing/downloading images I am using SDWebImage. 
                 });
             }
         }
    }
}
modusCell
  • 13,151
  • 9
  • 53
  • 80
  • Thank you, I'll try that tomorrow and report back! Do you find you need to do anything special to clean up the cells that are not in view? – user441669 Jul 25 '14 at 03:47
  • It was my original plan however once I have seen it does not affect performance I left it. If you want to clean them you can set imageView image to nil if cell is out of visible rect. – modusCell Jul 25 '14 at 12:49
  • 1
    Great solution. However I think NSIntersectsRect is a better way to determine if a view is in visible area. – Xhacker Liu Mar 16 '15 at 21:46
  • Hi, @mohacs, you say you're using SDWebImage to download images, but they don't support Mac, right? – Daniel Jun 30 '15 at 13:20
  • @Daniel SDWebImage support both OS X and IOS. – modusCell Jun 30 '15 at 13:22