Tôi có một ViewController với một CollectionView bên trong. Khi khung nhìn tải, các ô hiển thị (9 ô) được hiển thị chính xác. Khi tôi cuộn xuống, tôi muốn tải các mục hiển thị trong collectionview bằng loadImagesForOnscreenRows bằng cách gọi indexPathsForVisibleItems cho partnerCollectionView. Nhưng khi loadImagesForOnscreenRows indexPathsForVisibleItems có allways 9 ô đầu tiên trong đó, ngay cả khi các ô 10 đến 18 sẽ hiển thị trên màn hình. Code tôi sử dụng là:UICollectionView indexPathsForVisibleItems không cập nhật các ô hiển thị mới
#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
Và kết quả này trong đầu ra:
chương trình ban đầu các mặt hàng có thể nhìn thấy
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
Sau khi di chuyển đến mục 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
Như bạn có thể thấy sau khi cuộn, các đường dẫn chỉ mục có thể nhìn thấy vẫn giữ nguyên. Có ai khác đã gặp phải điều này hoặc một ý tưởng cho một giải pháp? Hoặc tôi không hiểu một số nguyên tắc của collectionview sai?
Rất cám ơn trước! Trân trọng, Jan
Tôi không có mục đích 'loadImagesForOnscreenRows'. Trong 'cellForRowAtIndexPath' bạn đặt hình ảnh nếu nó có sẵn. Nếu không, trong 'imageLoaderDidFinishDownloading' bạn có thể tải lại đường dẫn chỉ mục, nó sẽ gọi lại' cellForRowAtIndexPath' hoặc bạn có thể đặt trực tiếp hình ảnh trên ô nếu nó vẫn còn trên màn hình. Sẽ không bao gồm nó? –
Xin chào Timothy, 'cellForRowAtIndexPath' tải các ô hiển thị trong khung nhìn, trong trường hợp của tôi là 9 ô đầu tiên. Khi tôi bắt đầu cuộn, các ô sắp tới sẽ không được điền vào, thay vào đó 'scrollViewDidEndDragging' được gọi, sẽ gọi' loadImagesForOnscreenRows', giống như trong bảng xem trước. Trong hàm này, tôi muốn lấy các đường dẫn chỉ mục, 'indexPathsForVisibleItems', được hiển thị và bắt đầu tải xuống các hình ảnh, một khi chúng được tải xuống, hãy tải lại các đường dẫn chỉ mục. Nhưng 'indexPathsForVisibleItems' luôn trả về chín đầu tiên. Hay tôi đang làm điều gì đó hoàn toàn sai. Với bảng nó hoạt động tốt theo cách này. –
Các ô không có hình ảnh thường sẽ được điền riêng lẻ khi tải xuống cho ô đó hoàn tất, trong trường hợp của bạn sẽ xảy ra trong 'imageLoaderDidFinishDownloading'. Cho điều này, tôi không nhận được điểm của 'loadimageforOnscreenRows'. Nói cách khác, tại sao bạn không điền vào ô trong 'imageLoaderDidFinishDownloading'? –