2013-09-03 7 views
8

मेरे पास एक संग्रह दृश्य के साथ व्यू कंट्रोलर है। जब दृश्य लोड होता है, दृश्यमान कक्ष (9 कोशिकाएं) सही ढंग से दिखाए जाते हैं। जब मैं स्क्रॉल करता हूं, तो मैं पार्टनरवॉलव्यू व्यू के लिए indexPathsForVisibleItems को कॉल करके loadImagesForOnscreenRows के साथ संग्रह दृश्य में दृश्यमान आइटम लोड करना चाहता हूं। लेकिन जब loadImagesForOnscreen सूचकांक देता है PathsForVisibleItems में इसके पहले 9 कक्ष होते हैं, भले ही कक्ष 10 से 18 स्क्रीन पर दिखाई दे। कोड मैं का उपयोग करें:UICollectionView indexPathsForVisibleItems नई दृश्यमान कोशिकाओं को अपडेट नहीं करते

#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 

मदों की प्रारंभिक शो 19 आइटम 10 लोगों को स्क्रॉल करने के बाद:

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 

जैसा कि आप स्क्रॉलिंग के बाद देख सकते हैं, आइटम दिखाई देने वाले इंडेक्स पथ समान रहते हैं। क्या किसी और को इसका समाधान हुआ है या समाधान के लिए एक विचार है? या क्या मैं संग्रहदृश्य के कुछ सिद्धांत को गलत समझ रहा हूं?

अग्रिम में बहुत धन्यवाद! दयालु संबंध, जनवरी

+0

मुझे 'loadImagesForOnscreenRows' का उद्देश्य नहीं मिला है। 'CellForRowAtIndexPath' में आप छवि सेट करते हैं तो यह उपलब्ध है। अन्यथा, 'imageLoaderDidFinishDownloading' में आप इंडेक्स पथ को फिर से लोड कर सकते हैं, जो' cellForRowAtIndexPath' को फिर से कॉल करेगा या आप छवि पर सीधे स्क्रीन पर छवि को सेट कर सकते हैं। क्या वह इसे कवर नहीं करेगा? –

+0

हाय टिमोथी, 'cellForRowAtIndexPath' दृश्य में दिखाई देने वाली कोशिकाओं को लोड करता है, मेरे मामले में पहले नौ में। जब मैं स्क्रॉल करना शुरू करता हूं, तो आगामी कक्षों को भरना नहीं होगा, इसके बजाय 'scrollViewDidEndDragging' कहा जाता है, जो' loadImagesForOnscreenRows' को कॉलव्यूज़ में कॉल करेगा। इस फ़ंक्शन में मैं इंडेक्सपैथ प्राप्त करना चाहता हूं, 'इंडेक्सपाथ्सफॉरविज़िबल इटम्स', जो दृश्यमान हैं, और छवियों को डाउनलोड करना शुरू करने के बाद, डाउनलोड होने के बाद, इंडेक्सपाथ को पुनः लोड करें। लेकिन 'indexPathsForVisibleItems' हमेशा पहले नौ लौटाता है। या मैं कुछ पूरी तरह गलत कर रहा हूँ। तालिकाओं के साथ यह इस तरह से ठीक काम करता है। –

+0

जिन कोशिकाओं में छवियां नहीं हैं, वे आम तौर पर उस सेल के लिए डाउनलोड पूर्ण होने पर अलग-अलग भर जाएंगे, जो आपके मामले में 'imageLoaderDidFinishDownloading' में होगी। यह देखते हुए, मुझे 'loadimageforOnscreenRows' का बिंदु नहीं मिलता है। दूसरे शब्दों में, आप 'imageLoaderDidFinishDownloading' में सेल क्यों भर रहे हैं? –

उत्तर

5

यदि आप आईओएस 8.0 और ऊपर लक्षित कर रहे हैं तो आपको अपने डाउनलोड को बंद करने के लिए collectionView:willDisplayCell:forItemAtIndexPath: का उपयोग करना चाहिए। यदि आईओएस 7.0 का उपयोग करना है तो आपको collectionView:cellForItemAtIndexPath: का उपयोग करना जारी रखना चाहिए।

आपके imageLoaderDidFinishDownloading: कॉलबैक में आपको यह देखने के लिए जांच करनी चाहिए कि प्रश्न में इंडेक्स पथ अभी भी दिखाई दे रहा है या नहीं। यदि ऐसा है, तो संबंधित सेल पुनर्प्राप्त करें और इसके छवि दृश्य को अपडेट करें। यदि सेल दिखाई नहीं दे रहा है, तो आपका काम पूरा हो गया है। प्रत्येक छवि पूर्ण होने के लिए -reloadData पर कॉल करना बहुत महंगा काम कर रहा है और यदि आपका उपयोगकर्ता वर्तमान में तालिका का मध्य-स्क्रॉल है और आप इसकी सामग्री को रीसेट करते हैं तो महत्वपूर्ण यूएक्स समस्याएं हो सकती हैं। आप संभावित रूप से UIImageJPEGRepresentation() काम कर रहे हैं, यह आपके स्क्रॉलिंग प्रदर्शन में मदद करेगा यदि आपने imageLoaderDidFinishDownloading: में यह काम किया था और फिर इसे कैश किया था।

चूंकि ऐसा लगता है कि पृष्ठभूमि थ्रेड पर कॉलबैक होता है, यह सुनिश्चित करें कि आप केवल मुख्य थ्रेड से UICollectionView में हेरफेर करें।

संबंधित मुद्दे