项目中,有一个需求,是加载几张网络图片,每一张都要求宽度与屏幕宽度一样,然后高度自适应;并且几张自上而下一次排列。
这让我想到了UITableVIew,但是图片的处理成了问题,经过我多次的处理,完成了这个需求
大概的思路是:
1.重写自己的Cell,Cell中利用一个UIButton展示图片,而不是UIImageView,因为这样好控制图片的宽度与屏幕一致
2.每一个图片在未完成网络加载时,都有一张长款固定的HolderImage代替
3.UITableView cell 的height手动计算
首先是自定义Cell:
//
// PYClubPresentDetailImgTableViewCell.h
// iphone-pay
//
// Created by jinhui005 on 16/8/25.
// Copyright © 2016年 RHJX Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface PYClubPresentDetailImgTableViewCell : UITableViewCell
@property (nonatomic, strong) UIButton *btn;
@end
//
// PYClubPresentDetailImgTableViewCell.m
// iphone-pay
//
// Created by jinhui005 on 16/8/25.
// Copyright © 2016年 RHJX Inc. All rights reserved.
//
#import "PYClubPresentDetailImgTableViewCell.h"
@interface PYClubPresentDetailImgTableViewCell ()
@end
@implementation PYClubPresentDetailImgTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self.contentView addSubview:self.btn];
[self.btn mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.bottom.equalTo(self.contentView);
}];
}
return self;
}
- (UIButton *)btn {
if (nil == _btn) {
_btn = [[UIButton alloc] init];
_btn.titleLabel.font = kFT3;
_btn.userInteractionEnabled = NO;
}
return _btn;
}
@end
然后是UITableView的代理方法
#pragma mark - UITableViewDelegate, UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.imgArray.count;//图片URL以数组的形式存在
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// 先从缓存中查找图片
UIImage *image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey: self.imgArray[indexPath.row]];
// 没有找到已下载的图片就使用默认的占位图,当然高度也是默认的高度了,除了高度不固定的文字部分。
if (!image) {
image = [UIImage imageNamed:kDownloadImageHolder];
}
//手动计算cell
CGFloat imgHeight = image.size.height * [UIScreen mainScreen].bounds.size.width / image.size.width;
return imgHeight;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *imgID = @"pictureCellID";
PYClubPresentDetailImgTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:imgID];
if (nil == cell) {
cell = [[PYClubPresentDetailImgTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:imgID];
}
[self configureCell:cell atIndexPath:indexPath];
cell.userInteractionEnabled = NO;
return cell;
}
- (void)configureCell:(PYClubPresentDetailImgTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
NSString *imgURL = self.imgArray[indexPath.row];
UIImage *cachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:imgURL];
if ( !cachedImage ) {
[self downloadImage:self.imgArray[indexPath.row] forIndexPath:indexPath];
[cell.btn setBackgroundImage:[UIImage imageNamed:kDownloadImageHolder] forState:UIControlStateNormal];
} else {
[cell.btn setBackgroundImage:cachedImage forState:UIControlStateNormal];
}
}
- (void)downloadImage:(NSString *)imageURL forIndexPath:(NSIndexPath *)indexPath {
// 利用 SDWebImage 框架提供的功能下载图片
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:imageURL] options:SDWebImageDownloaderUseNSURLCache progress:^(NSInteger receivedSize, NSInteger expectedSize) {
// do nothing
} completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
[[SDImageCache sharedImageCache] storeImage:image forKey:imageURL toDisk:YES];
dispatch_async(dispatch_get_main_queue(), ^{
// [self.tableView reloadData];
// 延迟在主线程更新 cell 的高度
[target performSelectorOnMainThread:@selector(reloadCellAtIndexPath:) }];
// 至于这步的原因是为了防止刷的太快了崩溃 withObject:indexPath waitUntilDone:NO];
// 这步会把 selector 的调用放到主线程的 run loop 里排队
// 风险就是要是这个队列里排队的比较多,
// 这个后插入的方法执行会被延迟
});
}];
}
// 方法名为什么叫这个。。。。是我太懒了,之前写的是刷新某一行的数据,然后发现效率不高,还容易崩溃
// 最后直接刷新全部数据了。。
// 但是别认为调用 table view 的 reloadData 效率就不高,回顾下上面的步骤
// reloadData 实际上就是向代理要行数,要行高,对**显示出来**的 cell 填充数据
// 我的那份代码的瓶颈就是 计算行高和填充数据,不过现在看来没什么不流畅的,所以就没什么问题
// 其实,为了性能考虑,还是最好服务器返回 每个 cell 中的图片的宽高,现在的做法只是临时解决后台xx的问题。。。。。。
- (void)reloadCellAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView reloadData];
///个人注释
// 单行刷新
NSIndexPath *indexPath_1=[NSIndexPath indexPathForRow:1 inSection:0];
NSArray *indexArray=[NSArray arrayWithObject:indexPath_1];
[regTableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationAutomatic];
}
from:http://blog.csdn.net/icefishlily/article/details/52606221