异步将图像加载到自定义表格视图单元格中

时间:2013-02-26 11:59:31

标签: iphone objective-c uitableview ios6

目前,我正在开发一款应用程序,我可以在其中获取Facebook专辑照片&显示为 使用表视图&同步异步库视图使用以下代码将图像放在表格视图单元格的按钮上:

- (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;
    }

此代码对我来说工作正常,但问题是当图像加载到按钮包含表视图单元格然后如果我们向下滚动然后它慢慢显示图像但在此之后当我们向上滚动以查看先前加载图像时图像消失&安培;它再次从开始加载需要时间。所以请告诉我在代码中的错误,或者我该如何解决?

4 个答案:

答案 0 :(得分:3)

有一些自定义库可以很好地完成这项工作

  1. AsynchImageView
  2. SDWebImage
  3. AFNetworking图像扩展(如果您使用AF)

答案 1 :(得分:3)

我建议您使用此AsyncImageView。我已经习惯了,它可以创造奇迹。要调用此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.

与使用UIImageView相同。简单,它可以为您完成大部分工作。 AsyncImageView包含UIImageView上的一个简单类别,用于在iOS上异步加载和显示图像,以便它们不会锁定UI,以及用于更高级功能的UIImageView子类。 AsyncImageView适用于URL,因此可以与本地或远程文件一起使用。

加载/下载的图像缓存在内存中,并在发生内存警告时自动清除。 AsyncImageView独立于UIImage缓存运行,但默认情况下,位于应用程序包根目录中的任何图像都将存储在UIImage缓存中,从而避免重复缓存图像。

该库还可以独立于UIImageView加载和缓存图像,因为它提供了对底层加载和缓存类的直接访问。

答案 2 :(得分:1)

它的工作方式应该如此。当您滚动表格视图时,就好像已经释放的单元格已经被释放,当您向后滚动时,单元格会出列。 因此,您应该使用解决方案来缓存图像,以便不需要再次加载它们,例如EGOImageView(here),AsyncImageView,SDWebImage等。

答案 3 :(得分:0)

这是一个没有使用dispatch_async的解决方案。如果您从服务获取URL而不是使用此方法调用服务的NSObject

-(void)loadProfilePicWithURL:(NSString *)strUrl  tagV:(NSInteger)tagV{
isProfilePicLoaded = NO;
//set media tag as indexPath.row

//call this method from cellForRowAtIndexpPath
//Pass the image URL --> strProfilePicURL
//Load the image in bg and set to imgProfilePic
//After loaded, send a notification with tag to table view to update the cell


NSData *data=[NSData dataWithContentsOfURL:[NSURL URLWithString:strUrl]];
imgProfilePic=[UIImage imageWithData:data];

isProfilePicLoaded = YES;
[[NSNotificationCenter defaultCenter] postNotificationName:@"reloadTableViewCell" object:[NSNumber numberWithInteger:tagV]];
}

从cellForRowAtIndexPath

调用此方法
[self performSelectorInBackground:@selector(loadPic:) withObject:[NSNumber numberWithInteger:indexPath.row]];

实施

-(void)loadPic: (id )indexPath{
NSInteger conV=[indexPath integerValue];

NSObject *object=[Array objectAtIndex:conV];
[object loadProfilePicWithURL:object.url tagV:conV];

}

在NSObject中添加Observer以获取通知

-(void)reloadTableViewCell:(NSNotification *)note{
NSInteger mediaTag = [[note object] integerValue];

[self reloadCellImage:mediaTag];

}

重新加载表格中的特定单元格。

-(void)reloadCellImage:(NSInteger)row{
NSObject *object = [self.receivedArray objectAtIndex:row];
NSIndexPath* rowToReload = [NSIndexPath indexPathForRow:row inSection:0];
customCell *cell = (customCell *)[self.tableView cellForRowAtIndexPath:rowToReload];
[cell.imgVw setImage:object.image];}