Search code examples
iosuitableviewcachingsdwebimage

How to cache images properly in ios


I m using SDWebImage to cache image. But its not working. I am using it in this fashion under cellForRowAtIndexPath:

[cell.image sd_setImageWithURL:[NSURL URLWithString:[NSMutableString stringWithFormat:@"%@app/media/access/pictures?p=%@",baseurl,data.picPath]]
                 placeholderImage:[UIImage sd_animatedGIFNamed:@"image_loader.gif"] options:SDWebImageRefreshCached];

I suppose its downloading the images asynchronously. But my app freezes while scrolling the UITableView. And there is also network usage while scrolling up, for me that shouldn't happen as I am caching it.

Besides I have some logic to resize UIImageView frame according to image size under heightForRowAtIndexPath, could that be any reason???

if(data.type == 2)
    {
        height = 260.00;
    }
    else if(data.type == 1)
    {
        height = self.view.frame.size.width/2 + 115;
    }
    else
    {
        NSString *filePath = [NSString stringWithFormat:@"%@app/media/access/pictures?p=%@",baseurl,data.picPath];
        self.img = [UIImage imageWithData: [NSData dataWithContentsOfURL:[NSURL URLWithString:filePath]]];


        if (self.img.size.width > CGRectGetWidth(self.view.bounds)) {
            CGFloat ratio = self.img.size.height / self.img.size.width;
            return CGRectGetWidth(self.view.bounds) * ratio+120;
        } else {
            return self.img.size.height+110;
        }




    }

Solution

  • The Code below in your heightForRowAtIndexPath is causing issue:

    NSString *filePath = [NSString stringWithFormat:@"%@app/media/access/pictures?p=%@",baseurl,data.picPath];
            self.img = [UIImage imageWithData: [NSData dataWithContentsOfURL:[NSURL URLWithString:filePath]]];
    

    Code will executed every time you scroll tableView and it will cause freezing problem since it is not asynchronous call.

    Edit: To avoid that you can do something like this:

    when finished downloading you can use,

    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] 
                     withRowAnimation:UITableViewRowAnimationAutomatic];
    

    This will call again

        -(CGFloat)tableView:(UITableView *)tableView
    heightForRowAtIndexPath:(NSIndexPath *)indexPath
    

    Like,

    [cell.image sd_setImageWithURL:[NSURL URLWithString:[NSMutableString stringWithFormat:@"%@app/media/access/pictures?p=%@",baseurl,data.picPath]]
    
                                         completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
    
                                             if (error) {
    
                                                 NSLog(@"error: %@",error.description);
    
    
                                             }
                                             else{
    
                                                 //get image height and return this height from HeightForRowAtIndexPath
                                                 Height=image.size.height;
    
                                                 //reloading row will call heightForRowAtIndexPath,where now you can return height got above
                                                 [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationAutomatic];
    
                                                 NSLog(@"Not an error in image download");
                                             }
    
    
    
    
                                         }];
    

    Edit1:

    to check image already cached, you can use below method of SDWebImage library:

    - (BOOL)diskImageExistsWithKey:(NSString *)key;
    

    The cache key is an application unique identifier for the image to cache. It is generally the absolute URL of the image.

    Now if image exist in cache,then get image path using below methods of SDWebImage Library:

    - (NSString *)defaultCachePathForKey:(NSString *)key;
    - (NSString *)cachedFileNameForKey:(NSString *)key;
    

    You can get the path to your image like this:

    NSString *ImageKey;//key for the image you want the path for
    [[SDImageCache sharedImageCache] defaultCachePathForKey:ImageKey];
    

    in case you do not use the default location, you can use:

    - (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path;
    

    For more detail check here: SDWebImage