iphone - Smooth scrolling of UITableView with GIF images -


i have uitableview in app displays animating gif images downloaded web.

i've used background threads download images web , tmcache store images temporary on device. while downloading ui behaves expected i.e. tableview scroll smooth.

the problem arises when gif images gets downloaded , start animating. scroll not smooth graphic processing done on main thread.

i've tried doing gif animation on background thread, results unexpected takes long image loaded in uiimageview , start animating , loader shown.

one possible solution pause animation when tableview scrolling can't figure out how implement this.

can explain me implementation part or other solution?

thanks.

here code load images in cell:

+(void)loadimageincell:(id)cell atindexpath:(nsindexpath *)indexpath forurl:(nsurl *)url {     dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_high, 0ul), ^{         [[tmcache sharedcache] objectforkey:[url absolutestring]                                       block:^(tmcache *cache, nsstring *key, id object) {                                           if (object) {                                               [self setimagefromfileatpath:(nsstring *)object incell:cell atindexpath:indexpath];                                               return;                                           }                                            [self addloadingincell:cell atindexpath:indexpath];                                            nsarray *strings = [[url absolutestring] componentsseparatedbystring:@"/"];                                           nsstring *filename;                                           (nsstring *string in strings) {                                               if ([string rangeofstring:@".gif"].location != nsnotfound) {                                                   nsrange stoprange = [string rangeofstring:@".gif"];                                                   filename = [string substringtoindex:(stoprange.location + stoprange.length)];                                                   break;                                               }                                           }                                           nsarray *paths = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes);                                           nsstring *documentsdirectory = [paths objectatindex:0];                                           nsstring *filepath = [documentsdirectory stringbyappendingpathcomponent:filename];                                            if ([[nsfilemanager defaultmanager] fileexistsatpath:filepath]) {                                               [[tmcache sharedcache] setobject:filepath forkey:[url absolutestring]];                                               [self setimagefromfileatpath:filepath incell:cell atindexpath:indexpath];                                               return;                                           }                                            nsurlresponse *response = nil;                                           nsurlrequest *request = [nsurlrequest requestwithurl:url];                                           nsdata *data = [nsurlconnection sendsynchronousrequest:request returningresponse:&response error:nil];                                            if ([data writetofile:filepath atomically:yes]) {                                               [self setimagefromfileatpath:filepath incell:cell atindexpath:indexpath];                                               [[tmcache sharedcache] setobject:filepath forkey:[url absolutestring]];                                           }                                       }];     }); }  +(void)setimagefromfileatpath:(nsstring *)path incell:(id)cell atindexpath:(nsindexpath *)indexpath {     [self removeloadingfromcell:(uiview *)cell atindexpath:indexpath];     nsdata *imagedata = [nsdata datawithcontentsoffile:path];     dispatch_async(dispatch_get_main_queue(), ^{         if ([cell iskindofclass:[uitableviewcell class]]) {             [[(uitableviewcell *)cell imageview] setimage:nil];             [[(uitableviewcell *)cell imageview] setimage:[uiimage animatedimagewithanimatedgifdata:imagedata]];         } else {             uiimageview *imageview = (uiimageview *)[(uicollectionviewcell *)cell viewwithtag:1001];             [imageview setimage:nil];             [imageview setimage:[uiimage animatedimagewithanimatedgifdata:imagedata]];         }     }); }  +(void)addloadingincell:(id)cell atindexpath:(nsindexpath *)indexpath {     uiactivityindicatorview *activityindicator = [[uiactivityindicatorview alloc] initwithactivityindicatorstyle:uiactivityindicatorviewstylegray];     [activityindicator settag:5001];     if ([cell iskindofclass:[uitableviewcell class]]) {         dispatch_async(dispatch_get_main_queue(), ^{             uitableviewcell *tablecell = (uitableviewcell *)cell;             [activityindicator setcenter:tablecell.imageview.center];             [tablecell addsubview:activityindicator];             [activityindicator startanimating];         });     } else {         dispatch_async(dispatch_get_main_queue(), ^{             uicollectionviewcell *collectioncell = (uicollectionviewcell *)cell;             uiimageview *imageview = (uiimageview *)[collectioncell viewwithtag:1001];             [activityindicator setcenter:imageview.center];             [imageview addsubview:activityindicator];             [activityindicator startanimating];         });     } }  +(void)removeloadingfromcell:(uiview *)cell atindexpath:(nsindexpath *)indexpath {     dispatch_async(dispatch_get_main_queue(), ^{         uiview *activityview = [cell viewwithtag:5001];         if (activityview) {             [activityview removefromsuperview];         }     }); } 

images animated following code:

static int delaycentisecondsforimageatindex(cgimagesourceref const source, size_t const i) {     int delaycentiseconds = 1;     cfdictionaryref const properties = cgimagesourcecopypropertiesatindex(source, i, null);     if (properties) {         cfdictionaryref const gifproperties = cfdictionarygetvalue(properties, kcgimagepropertygifdictionary);         cfrelease(properties);         if (gifproperties) {             cfnumberref const number = cfdictionarygetvalue(gifproperties, kcgimagepropertygifdelaytime);             // though gif stores delay integer number of centiseconds, imageio “helpfully” converts seconds us.             delaycentiseconds = (int)lrint([fromcf number doublevalue] * 100);         }     }     return delaycentiseconds; }  static void createimagesanddelays(cgimagesourceref source, size_t count, cgimageref imagesout[count], int delaycentisecondsout[count]) {     (size_t = 0; < count; ++i) {         imagesout[i] = cgimagesourcecreateimageatindex(source, i, null);         delaycentisecondsout[i] = delaycentisecondsforimageatindex(source, i);     } }  static int sum(size_t const count, int const *const values) {     int thesum = 0;     (size_t = 0; < count; ++i) {         thesum += values[i];     }     return thesum; }  static int pairgcd(int a, int b) {     if (a < b)         return pairgcd(b, a);     while (true) {         int const r = % b;         if (r == 0)             return b;         = b;         b = r;     } }  static int vectorgcd(size_t const count, int const *const values) {     int gcd = values[0];     (size_t = 1; < count; ++i) {         // note after process first few elements of vector, `gcd` smaller remaining element.  passing smaller value second argument `pairgcd`, avoid making swap arguments.         gcd = pairgcd(values[i], gcd);     }     return gcd; }  static nsarray *framearray(size_t const count, cgimageref const images[count], int const delaycentiseconds[count], int const totaldurationcentiseconds) {     int const gcd = vectorgcd(count, delaycentiseconds);     size_t const framecount = totaldurationcentiseconds / gcd;     uiimage *frames[framecount];     (size_t = 0, f = 0; < count; ++i) {         uiimage *const frame = [uiimage imagewithcgimage:images[i]];         (size_t j = delaycentiseconds[i] / gcd; j > 0; --j) {             frames[f++] = frame;         }     }     return [nsarray arraywithobjects:frames count:framecount]; }  static void releaseimages(size_t const count, cgimageref const images[count]) {     (size_t = 0; < count; ++i) {         cgimagerelease(images[i]);     } }  static uiimage *animatedimagewithanimatedgifimagesource(cgimagesourceref const source) {     size_t const count = cgimagesourcegetcount(source);     cgimageref images[count];     int delaycentiseconds[count]; // in centiseconds     createimagesanddelays(source, count, images, delaycentiseconds);     int const totaldurationcentiseconds = sum(count, delaycentiseconds);     nsarray *const frames = framearray(count, images, delaycentiseconds, totaldurationcentiseconds);     uiimage *const animation = [uiimage animatedimagewithimages:frames duration:(nstimeinterval)totaldurationcentiseconds / 100.0];     releaseimages(count, images);     return animation; }  static uiimage *animatedimagewithanimatedgifreleasingimagesource(cgimagesourceref source) {     if (source) {         uiimage *const image = animatedimagewithanimatedgifimagesource(source);         cfrelease(source);         return image;     } else {         return nil;     } }  + (uiimage *)animatedimagewithanimatedgifdata:(nsdata *)data {     return animatedimagewithanimatedgifreleasingimagesource(cgimagesourcecreatewithdata(tocf data, null)); }  + (uiimage *)animatedimagewithanimatedgifurl:(nsurl *)url {     return animatedimagewithanimatedgifreleasingimagesource(cgimagesourcecreatewithurl(tocf url, null)); } 

thanks.


Comments

Popular posts from this blog

basic authentication with http post params android -

vb.net - Virtual Keyboard commands -

css - Firefox for ubuntu renders wrong colors -