【问题标题】:Load images into custom table view cell asynchronously将图像异步加载到自定义表格视图单元格中
【发布时间】:2015-03-03 19:52:51
【问题描述】:

目前,我正在开发一个应用程序,我可以在其中获取 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;
    }

这段代码对我来说工作正常,但问题是当图像加载到由表格视图单元格包含的按钮时,如果我们向下滚动,它会慢慢显示图像,但之后当我们向上滚动查看之前加载的图像时,图像就会消失&它再次从开始加载并花费时间。所以请告诉我在代码中做错了什么或者我该如何解决这个问题?

【问题讨论】:

  • 用于缓慢加载图像,并且由于 tableview 可重用单元格而再次开始重新加载。如果将这些图像添加到数组中并将该图像数组加载到 tableview 中会很好

标签: iphone objective-c uitableview ios6


【解决方案1】:

我建议你使用这个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. AsynchImageView
    2. SDWebImage
    3. AFNetworking 图像扩展(如果您使用的是 AF)

    【讨论】:

    • Lithu 是正确的。您可以使用任何可以轻松完成工作的工具。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      这是一个不使用 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 中为通知添加观察者

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

      【讨论】:

        猜你喜欢
        • 2018-07-02
        • 2011-10-30
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-29
        相关资源
        最近更新 更多