Search code examples
iphoneobjective-cuitableviewios6

Load images into custom table view cell asynchronously


Currently, I am developing an app in which I have fetch Facebook album photo & display it as gallery view asynchronously using Table view & put images on button of table view cell using below code:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSLog(@"particulars..:%d",[particular count]);
    int count=self.particular.count%3;

    if(count==0)
    {
        return self.particular.count/3;
    }
    else
    {
        return (self.particular.count/3) +1;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell1";
    CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
     if (cell == nil)
        {
            [[NSBundle mainBundle] loadNibNamed:@"CustomTableViewCell" owner:self options:nil];
            cell = customcell;
        }


    UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];

        dispatch_async(dispatch_get_global_queue(0,0), ^{
            NSString *buttonurl=[self.particular objectAtIndex:((indexPath.row)*3)+0];
            NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: buttonurl]];
            if ( data == nil )
                return;
            dispatch_async(dispatch_get_main_queue(), ^{


                UIImage *image = [UIImage imageWithData:data];
                cell.accessoryType = UITableViewCellAccessoryNone;
                cell.selectionStyle = UITableViewCellSelectionStyleNone;
                cell.backgroundColor=[UIColor clearColor];
                [cell.first setBackgroundImage:image forState:UIControlStateNormal] ;
                [cell.first addTarget:self action:@selector(original:) forControlEvents:UIControlEventTouchUpInside];
                [cell.first setContentMode:UIViewContentModeCenter] ;
                cell.first.layer.cornerRadius = 10.0;
                cell.first.layer.borderColor = [[UIColor grayColor]CGColor];
                cell.first.layer.borderWidth = 1.0f;
                cell.first.backgroundColor=[UIColor clearColor];
                cell.first.tag = ((indexPath.row)*3)+1 ;
                [spinner stopAnimating];
            });
            [data release];
        });

        if(((indexPath.row)*3)+3<[particular count])
        {
            UIActivityIndicatorView *spinner2 = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            UIActivityIndicatorView *spinner3 = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            //spinner2.backgroundColor=[UIColor blackColor];
            CGRect frame= cell.second.frame;
            spinner2.frame=frame;
            //spinner2.frame=CGRectMake(112, y, 106, 106);
            spinner2.hidesWhenStopped = YES;
            [cell.second addSubview:spinner2];
            [spinner2 startAnimating];

            CGRect frame2= cell.third.frame;
            spinner3.frame=frame2;
            spinner3.hidesWhenStopped = YES;
            [cell.third addSubview:spinner3];
            [spinner3 startAnimating];

            dispatch_async(dispatch_get_global_queue(0,0), ^
            {
                NSString *buttonurl=[self.particular objectAtIndex:((indexPath.row)*3)+1];
                NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: buttonurl]];

                NSString *buttonurl1=[self.particular objectAtIndex:((indexPath.row)*3)+2];
                NSData * data1 = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: buttonurl1]];
                if ( data == nil )
                    return;
                dispatch_async(dispatch_get_main_queue(), ^
                {
                    UIImage *image = [UIImage imageWithData:data];
                    UIImage *image1 = [UIImage imageWithData:data1];

                    [cell.second setBackgroundImage:image forState:UIControlStateNormal] ;
                    [cell.second addTarget:self action:@selector(original:) forControlEvents:UIControlEventTouchUpInside];
                    [cell.second setContentMode:UIViewContentModeCenter] ;
                    cell.second.layer.cornerRadius = 10.0;
                    cell.second.layer.borderColor = [[UIColor grayColor]CGColor];
                    cell.second.layer.borderWidth = 1.0f;
                    cell.second.backgroundColor=[UIColor clearColor];
                    cell.second.tag = ((indexPath.row)*3)+2 ;
                    NSLog(@"cell.second.tag:%d",cell.second.tag);

                    [cell.third setBackgroundImage:image1 forState:UIControlStateNormal] ;
                    [cell.third addTarget:self action:@selector(original:) forControlEvents:UIControlEventTouchUpInside];
                    [cell.third setContentMode:UIViewContentModeCenter] ;
                    cell.third.layer.cornerRadius = 10.0;
                    cell.third.layer.borderColor = [[UIColor grayColor]CGColor];
                    cell.third.layer.borderWidth = 1.0f;

                    cell.third.backgroundColor=[UIColor clearColor];
                    cell.third.tag = ((indexPath.row)*3)+3 ;
                    NSLog(@"cell.third.tag:%d",cell.third.tag);
                    [spinner2 stopAnimating];
                    [spinner3 stopAnimating];

                });
                [data release];
            });


        }
        else if(((indexPath.row)*3)+2<[particular count])
        {
            UIActivityIndicatorView *spinner2 = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            CGRect frame1 = CGRectMake(120, y, 106, 107);
            spinner2.frame=frame1;
            spinner2.hidesWhenStopped = YES;
            [cell.second addSubview:spinner2];
            [spinner2 startAnimating];
            dispatch_async(dispatch_get_global_queue(0,0), ^
            {
                NSString *buttonurl=[self.particular objectAtIndex:((indexPath.row)*3)+1];
                NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: buttonurl]];
                if ( data == nil )
                    return;
                dispatch_async(dispatch_get_main_queue(), ^
                {
                    UIImage *image = [UIImage imageWithData:data];
                    [cell.second setBackgroundImage:image forState:UIControlStateNormal] ;
                    [cell.second addTarget:self action:@selector(original:) forControlEvents:UIControlEventTouchUpInside];
                    [cell.second setContentMode:UIViewContentModeCenter] ;
                    cell.second.layer.cornerRadius = 10.0;
                    cell.second.layer.borderColor = [[UIColor grayColor]CGColor];
                    cell.second.layer.borderWidth = 1.0f;
                    cell.second.backgroundColor=[UIColor clearColor];
                    cell.second.tag = ((indexPath.row)*3)+2 ;
                    NSLog(@"cell.second.tag:%d",cell.second.tag);
                    [spinner2 stopAnimating];

                });
                [data release];
            });         
        }
        else
        {
            cell.second.hidden = YES;
            cell.third.hidden = YES;
        }
        y=y+106;
        return cell;
    }

This code is working fine for me but the problem is that when images load into button contain by table view cell then if we scroll down then it slowly show images but after that when we scroll up to see previously load images then images disappear & it again load from starting & take times.So please tell where i am doing mistake in code or how can I solve this?


Solution

  • I'd suggest you to use this AsyncImageView. I've used it and it work wonders. To call this API:

    ASyncImage *img_EventImag = alloc with frame;
    NSURL *url = yourPhotoPath;
    [img_EventImage loadImageFromURL:photoPath];
    [self.view addSubView:img_EventImage]; // In your case you'll add in your TableViewCell.
    

    It's same as using UIImageView. Easy and it does most of the things for you. AsyncImageView includes both a simple category on UIImageView for loading and displaying images asynchronously on iOS so that they do not lock up the UI, and a UIImageView subclass for more advanced features. AsyncImageView works with URLs so it can be used with either local or remote files.

    Loaded/downloaded images are cached in memory and are automatically cleaned up in the event of a memory warning. The AsyncImageView operates independently of the UIImage cache, but by default any images located in the root of the application bundle will be stored in the UIImage cache instead, avoiding any duplication of cached images.

    The library can also be used to load and cache images independently of a UIImageView as it provides direct access to the underlying loading and caching classes.