繁体   English   中英

在tableview中异步设置图像

[英]Asynchronously set images in tableview

我有一个使用自定义单元格的TableView 我最初是在cellForRowAtIndexPath方法中设置从URL抓取图像

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"SimpleTableCell";

    SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (cell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"SimpleTableCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];
    }

    NSDictionary *dictObject = [places objectAtIndex:indexPath.row];
    cell.nameLabel.text  = [dictObject valueForKey:@"PlaceTitle"];

    NSURL *url = [NSURL URLWithString:@"http://images1.fanpop.com/images/image_uploads/Mario-Kart-Wii-Items-mario-kart-1116309_600_600.jpg"];
    NSData *data = [NSData dataWithContentsOfURL:url];
    UIImage *image = [UIImage imageWithData:data];
    cell.thumbnailImageView.image = image;

    return cell;
}

但这使我的TableView滚动不方便。 删除图像提取后,它可以正常滚动,因此我知道这是我的问题。

我的问题是:如何异步获取此图像并将其设置在单元格中? 是否有捷径可寻? 谢谢!

步骤1:拥有一个包含图像的缓存。 要么只是在内存中,要么在磁盘上更好。

步骤2:当您需要图像时,调用一个方法,该方法或者从缓存中返回图像,或者返回默认图像并开始下载。

步骤3:下载完成后,将图像添加到缓存中。 然后找出需要图像的行。 重新加载所有重新加载图像的行。

下载应使用GCD异步完成。 我真的建议您将下载代码添加到单独的可重用方法中,以便您处理下载错误。 即使您现在不执行此操作,也将在以后执行。

正如Apple文档所述,dataWithContentsOfURL是一种同步方法,而不是异步方法。

此方法非常适合将data:// URL转换为NSData对象,也可用于同步读取短文件。 如果需要读取可能较大的文件,请使用inputStreamWithURL:打开流,然后一次读取一段文件。

为了异步加载图像,尤其是在tableViewCell中,请尝试使用第3部分库SDWebImage

在表格视图cellforindexpath中使用此代码

 NSURLRequest *req =[[NSURLRequest alloc]initWithURL:[NSURL URLWithString:@"yourimageurl.com"]];

[NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if(!error){
        UIImage *image =[UIImage imageWithData:data];
        cell.thumbnailImageView.image = image;
    }
     else{
            //error
   }


}];
  1. 创建UIImageView类文件(我将其命名为MJTableImageView)。

MJTableImageView.h文件中

    @interface MJTableImageView : UIImageView< NSURLConnectionDelegate, NSURLConnectionDataDelegate >

    {
    NSMutableData *imageData ;
    long long expectedLength;
    NSURLConnection *currentConnection;
    NSString *File_name;

    }
    @property(nonatomic,readonly)UIActivityIndicatorView *loadingIndicator;
    @property(nonatomic)BOOL showLoadingIndicatorWhileLoading;

    -(void)setImageUrl:(NSURL *)imageUrl fileName:(NSString *)name;

    @end

MJTableImageView.m文件中

-(void)setImageUrl:(NSURL *)imageUrl fileName:(NSString *)name
{
    // discard the previous connection
    if(currentConnection)
    {
        [currentConnection cancel];
    }

    File_name = name;

    //reset current image
    self.image = nil;


//    if(_showLoadingIndicatorWhileLoading)
//    {
        //show the loading indicator

        if(!_loadingIndicator)
        {
            CGFloat width = self.bounds.size.width*0.5;

            _loadingIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake((self.bounds.size.width-width)/2, (self.bounds.size.height-width)/2, 25.0 , 25.0)];
            _loadingIndicator.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.5];
            _loadingIndicator.layer.cornerRadius = width*0.1;
        }
        [self startLoadingIndicator];
//    }

    // initialize the placeholder data
    imageData = [NSMutableData data];


    // start the connection
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:imageUrl];
    request.cachePolicy = NSURLRequestUseProtocolCachePolicy;

    currentConnection = [NSURLConnection connectionWithRequest:request delegate:self];



}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    //if the image view is reused in a table view for example to load another image  previous image is discarded
    if(connection != currentConnection)
    {
        [connection cancel];
        [self cleanUp];
        return;
    }

    // append new Data
    [imageData appendData:data];



    // show the partially loaded image
    self.image = [UIImage imageWithData:imageData];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    expectedLength = response.expectedContentLength;
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    // clean up
    [self cleanUp];

}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // show the full image
    self.image = [UIImage imageWithData:imageData];

    NSString *filename = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@", File_name];
    NSData *data = UIImagePNGRepresentation([UIImage imageWithData:imageData]);
    [data writeToFile:filename atomically:YES];

    // clean up
    [self cleanUp];
}
-(void)cleanUp
{
    // clean up
    imageData = nil;
    [self stopLoadingIndicator];
}
-(void)startLoadingIndicator
{
    if(!_loadingIndicator.superview)
    {
        [self addSubview:_loadingIndicator];
    }
    [_loadingIndicator startAnimating];
}
-(void)stopLoadingIndicator
{
    if(_loadingIndicator.superview)
    {
        [_loadingIndicator removeFromSuperview];
    }
    [_loadingIndicator stopAnimating];
}

我正在使用StoryBoard,所以我将ImageClass(MJTableImageView)文件添加到UItableviewcell ImageView并为其设置标签号。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    NSDictionary *dict = [self.arr objectAtIndex:indexPath.row];

    UITableViewCell *cell = [self.MJTableView dequeueReusableCellWithIdentifier:@"MJImageCell"];
    if(cell == nil)
    {

    }
    UILabel *appName = (UILabel*)[cell.contentView viewWithTag:2];
    appName.text = [dict valueForKey:@"trackName"];

    MJTableImageView *imageview = (MJTableImageView *)[cell.contentView viewWithTag:1];

    NSString *url = [dict valueForKey:@"artworkUrl60"];

    NSString *filename = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@",[dict valueForKey:@"trackName"] ];
    NSData *data = [NSData dataWithContentsOfFile:filename];
    if(data)
    {
        imageview.image = [UIImage imageWithData:data];
    }
    else
    {
        [imageview setImageUrl:[NSURL URLWithString:url] fileName:[dict valueForKey:@"trackName"]];
    }
    return  cell;
}

有关更多详细信息,请参见Github项目MJTableImageSwift,它位于Swift中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM