UICollectionView indexPathsForVisibleItems不更新新的可见单元格

我有一个ViewView里面有一个CollectionView。 加载视图时,可见单元格(9个单元格)正确显示。 当我向下滚动时,我想通过调用indexPathsForVisibleItems for partnerCollectionView在loadImagesForOnscreenRows中加载collectionView中的可见项。 但是,当loadImagesForOnscreenRows indexPathsForVisibleItems总是前9个单元格,即使单元格10到18应该在屏幕上可见。 我使用的代码是:

#import "PartnerListViewController.h" #import "AppDelegate.h" #import "Partner.h" #import "ImageLoader.h" #import "PartnerDetailViewController.h" @interface PartnerListViewController () @end @implementation PartnerListViewController @synthesize lblTitle; @synthesize partnerCollectionView; @synthesize imageDownloadsInProgress; @synthesize fetchedResultsController; @synthesize managedObjectContext; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. AppDelegate * appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate]; managedObjectContext = [appDelegate managedObjectContext]; imageDownloadsInProgress = [NSMutableDictionary dictionary]; appDelegate = nil; [self setupFetchedResultsController]; [partnerCollectionView reloadData]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Collection view data source - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return [[fetchedResultsController sections] count]; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section]; return [sectionInfo numberOfObjects]; } -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"PartnerCell"; UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath]; Partner *partner = [self.fetchedResultsController objectAtIndexPath:indexPath]; UIImageView *imageView = (UIImageView *)[cell viewWithTag:100]; if (!partner.image) { imageView.image = [UIImage imageNamed:@"annotationMap.png"]; if (self.partnerCollectionView.dragging == NO && self.partnerCollectionView.decelerating == NO) { [self startDownload:partner.imageUrl forIndexPath:indexPath]; } } else { imageView.image = [UIImage imageWithData:partner.image]; } UILabel *lblTitlePartner = (UILabel *)[cell viewWithTag:101]; lblTitlePartner.text = partner.title; lblTitlePartner.font = [UIFont fontWithName:fontName size:10]; return cell; } #pragma mark - Table cell image support - (void)startDownload:(NSString *)urlString forIndexPath:(NSIndexPath *)indexPath { NSLog(@"startDownload:%ld", (long)indexPath.row); ImageLoader *imageLoader = [imageDownloadsInProgress objectForKey:indexPath]; imageLoader = [[ImageLoader alloc] init]; imageLoader.urlString = urlString; imageLoader.indexPathTableView = indexPath; imageLoader.delegate = (id)self; [imageDownloadsInProgress setObject:imageLoader forKey:indexPath]; [imageLoader startDownload]; } // this method is used in case the user scrolled into a set of cells that don't have their app icons yet - (void)loadImagesForOnscreenRows { NSArray *visiblePaths = [self.partnerCollectionView indexPathsForVisibleItems]; NSMutableArray *rowsArray = [NSMutableArray arrayWithCapacity:[visiblePaths count]]; [visiblePaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) { NSLog(@"loadImagesForOnscreenRows1%@", @(indexPath.item)); [rowsArray addObject:@(indexPath.item)]; }]; for (NSIndexPath *indexPath in visiblePaths) { NSLog(@"loadImagesForOnscreenRows2:%ld", (long)indexPath.row); Partner *item = [self.fetchedResultsController objectAtIndexPath:indexPath]; if (!item.image) // avoid the app icon download if the app already has an icon { [self startDownload:item.imageUrl forIndexPath:indexPath]; } } } // called by our ImageDownloader when an icon is ready to be displayed - (void)imageLoaderDidFinishDownloading:(NSIndexPath *)indexPath { NSLog(@"imageLoaderDidFinishDownloading:%ld", (long)indexPath.row); ImageLoader *imageLoader = [imageDownloadsInProgress objectForKey:indexPath]; if (imageLoader != nil) { // Save the newly loaded image Partner *item = [self.fetchedResultsController objectAtIndexPath:indexPath]; item.image = UIImageJPEGRepresentation(imageLoader.image, 1.0); [self performSelectorOnMainThread:@selector(saveItem) withObject:nil waitUntilDone:YES]; [self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; } } - (void)saveItem { [self.managedObjectContext save:nil]; } - (void)reloadData { [self.partnerCollectionView reloadData]; } #pragma mark deferred image loading (UIScrollViewDelegate) // Load images for all onscreen rows when scrolling is finished - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (!decelerate) { [self loadImagesForOnscreenRows]; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { [self loadImagesForOnscreenRows]; } - (void)setupFetchedResultsController { // 1 - Decide what Entity you want NSString *entityName = @"Partner"; // Put your entity name here NSLog(@"Setting up a Fetched Results Controller for the Entity named %@", entityName); // 2 - Request that Entity NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName]; // 4 - Sort it if you want request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:NO selector:@selector(localizedCaseInsensitiveCompare:)]]; // 5 - Fetch it self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil]; NSError *error = nil; if (![[self fetchedResultsController] performFetch:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } } @end 

结果如下:

初始显示可见的项目

 2013-09-02 06:45:21.940 [2564:c07] startDownload:0 2013-09-02 06:45:21.943 [2564:c07] imageLoaderDidFinishDownloading:0 2013-09-02 06:45:21.950 [2564:c07] startDownload:1 2013-09-02 06:45:21.951 [2564:c07] imageLoaderDidFinishDownloading:1 2013-09-02 06:45:21.958 [2564:c07] startDownload:2 2013-09-02 06:45:21.959 [2564:c07] imageLoaderDidFinishDownloading:2 2013-09-02 06:45:21.965 [2564:c07] startDownload:3 2013-09-02 06:45:22.063 [2564:c07] imageLoaderDidFinishDownloading:3 2013-09-02 06:45:22.072 [2564:c07] startDownload:4 2013-09-02 06:45:22.073 [2564:c07] imageLoaderDidFinishDownloading:4 2013-09-02 06:45:22.081 [2564:c07] startDownload:5 2013-09-02 06:45:22.082 [2564:c07] imageLoaderDidFinishDownloading:5 2013-09-02 06:45:22.089 [2564:c07] startDownload:6 2013-09-02 06:45:22.090 [2564:c07] imageLoaderDidFinishDownloading:6 2013-09-02 06:45:22.098 [2564:c07] startDownload:7 2013-09-02 06:45:22.099 [2564:c07] imageLoaderDidFinishDownloading:7 2013-09-02 06:45:22.104 [2564:c07] startDownload:8 2013-09-02 06:45:22.163 [2564:c07] imageLoaderDidFinishDownloading:8 

滚动到第10项到第19项之后:

 2013-09-02 06:45:26.212 [2564:c07] loadImagesForOnscreenRows1:8 2013-09-02 06:45:26.212 [2564:c07] loadImagesForOnscreenRows1:0 2013-09-02 06:45:26.212 [2564:c07] loadImagesForOnscreenRows1:1 2013-09-02 06:45:26.212 [2564:c07] loadImagesForOnscreenRows1:6 2013-09-02 06:45:26.213 [2564:c07] loadImagesForOnscreenRows1:2 2013-09-02 06:45:26.213 [2564:c07] loadImagesForOnscreenRows1:3 2013-09-02 06:45:26.213 [2564:c07] loadImagesForOnscreenRows1:4 2013-09-02 06:45:26.213 [2564:c07] loadImagesForOnscreenRows1:5 2013-09-02 06:45:26.213 [2564:c07] loadImagesForOnscreenRows1:7 2013-09-02 06:45:26.214 [2564:c07] loadImagesForOnscreenRows2:8 2013-09-02 06:45:26.214 [2564:c07] loadImagesForOnscreenRows2:0 2013-09-02 06:45:26.214 [2564:c07] loadImagesForOnscreenRows2:1 2013-09-02 06:45:26.214 [2564:c07] loadImagesForOnscreenRows2:6 2013-09-02 06:45:26.214 [2564:c07] loadImagesForOnscreenRows2:2 2013-09-02 06:45:26.215 [2564:c07] loadImagesForOnscreenRows2:3 2013-09-02 06:45:26.215 [2564:c07] loadImagesForOnscreenRows2:4 2013-09-02 06:45:26.215 [2564:c07] loadImagesForOnscreenRows2:5 2013-09-02 06:45:26.215 [2564:c07] loadImagesForOnscreenRows2:7 

正如您在滚动后可以看到的那样,项目可见的索引path保持不变。 有没有其他人遇到这个或想法的解决scheme? 或者,我是不是把一些collectionview的原理弄错了呢?

提前谢谢了! 亲切的问候,1月

如果你的目标是iOS 8.0以上,你应该使用collectionView:willDisplayCell:forItemAtIndexPath:启动你的下载。 如果使用iOS 7.0,则应继续使用collectionView:cellForItemAtIndexPath:

在你的imageLoaderDidFinishDownloading:callback中,你应该检查是否仍然可见索引path。 如果是,请检索相应的单元格并更新其图像视图。 如果细胞不可见,那么你的工作就完成了。 为每个图像完成调用-reloadData花费大量昂贵的工作,并且如果您的用户当前正在滚动表格并重置其内容,则可能会出现重大的用户体验问题。 你也可能在做UIImageJPEGRepresentation()工作很多次,如果你在imageLoaderDidFinishDownloading:做了UIImageJPEGRepresentation()这样的工作,它会帮助你的滚动性能imageLoaderDidFinishDownloading:然后caching它。

由于看起来callback发生在后台线程上,所以确保你只能从主线程操纵UICollectionView