ios - UICollectionView indexPathsForVisibleItems don't update new visible cells -


i have viewcontroller collectionview inside. when view loads, visible cells (9 cells) shown correctly. when scroll down, want load visible items in collectionview loadimagesforonscreenrows calling indexpathsforvisibleitems partnercollectionview. when loadimagesforonscreenrows indexpathsforvisibleitems has allways first 9 cells in it, when cells 10 18 should visible on screen. code use is:

#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];    // additional setup after loading 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 resources can 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]; }  // method used in case user scrolled set of cells don't have 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)];    }];    (nsindexpath *indexpath in visiblepaths)    {        nslog(@"loadimagesforonscreenrows2:%ld", (long)indexpath.row);         partner *item = [self.fetchedresultscontroller objectatindexpath:indexpath];         if (!item.image) // avoid app icon download if app has icon        {            [self startdownload:item.imageurl forindexpath:indexpath];        }    } }  // called our imagedownloader when icon ready displayed - (void)imageloaderdidfinishdownloading:(nsindexpath *)indexpath {    nslog(@"imageloaderdidfinishdownloading:%ld", (long)indexpath.row);     imageloader *imageloader = [imagedownloadsinprogress objectforkey:indexpath];    if (imageloader != nil)    {        // save 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 onscreen rows when scrolling finished - (void)scrollviewdidenddragging:(uiscrollview *)scrollview willdecelerate:(bool)decelerate {    if (!decelerate) {        [self loadimagesforonscreenrows];    } }  - (void)scrollviewdidenddecelerating:(uiscrollview *)scrollview {    [self loadimagesforonscreenrows]; }  - (void)setupfetchedresultscontroller {    // 1 - decide entity want    nsstring *entityname = @"partner"; // put entity name here    nslog(@"setting fetched results controller entity named %@", entityname);     // 2 - request entity    nsfetchrequest *request = [nsfetchrequest fetchrequestwithentityname:entityname];     // 4 - sort if want    request.sortdescriptors = [nsarray arraywithobject:[nssortdescriptor sortdescriptorwithkey:@"title" ascending:no selector:@selector(localizedcaseinsensitivecompare:)]];    // 5 - fetch    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 

and result in output:

initial show of visible items

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 

after scrolling item 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 

as can see after scrolling, items visible index paths stay same. has else encountered or idea solution? or unsterstanding principle of collectionview wrong?

many in advance! kind regards, jan

if targeting ios 8.0 , above should use collectionview:willdisplaycell:foritematindexpath: kick off download. if using ios 7.0 should continue use collectionview:cellforitematindexpath:.

in imageloaderdidfinishdownloading: callback should check see if index path in question still visible. if is, retrieve corresponding cell , update image view. if cell isn't visible, work done. calling -reloaddata every image completion doing lot of expensive work , have significant ux issues if user mid-scroll of table , reset contents. potentially doing uiimagejpegrepresentation() work many times, scrolling performance if did work once in imageloaderdidfinishdownloading: , cached it.

since looks callback happens on background thread make sure manipulate uicollectionview main thread.


Comments

Popular posts from this blog

html - How to style widget with post count different than without post count -

How to remove text and logo OR add Overflow on Android ActionBar using AppCompat on API 8? -

javascript - storing input from prompt in array and displaying the array -