tableview是iOS客户端常用控件,对于电商类及新闻展示类的app来说,提高页面流畅度是很有必要的。
那么我今天就来提个方案
具体思路就是判断内存中是否已经有图片,有就从内存中取,没有就下载,这样可以降低用户流量量费
判断当前tableview的滑动状态和滑动动画
如果tableview处于滑动状态和有滑动动画状态就不进行下载图片,显示占位图片,当不在处于滑动再下载图片,这样就可以让界面更流畅,也可以避免下载不在视图上和用户不关心的内容。
请看代码和配图
#import "ViewController.h"
#import "Obj.h"
@interfaceViewController()<UITableViewDelegate,UITableViewDataSource,UIScrollViewDelegate>
@property (strong, nonatomic) IBOutlet UITableView *tableview;
@property (strong, nonatomic) NSMutableArray * arr;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString*url=@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1530294770034&di=25e69abdf249a30253afff5beb7876cc&imgtype=0&src=http%3A%2F%2Fc.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2Fcefc1e178a82b901e004bbc17f8da9773812ef93.jpg";
_arr = [NSMutableArray array];
for (int i = 0 ; i<100; i++) {
Obj * obj = [[Obj alloc]init];
obj.name = [NSString stringWithFormat:@"性能测试%d",i];
obj.url = url;
[_arr addObject:obj];
}
_tableview.rowHeight = 80;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _arr.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString * ids = @"cell";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:ids];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ids];
} else//当页面拉动的时候 当cell存在并且最后一个存在 把它进行删除就出来一个独特的cell我们在进行数据配置即可避免
{
while ([cell.contentView.subviews lastObject] != nil) {
[(UIView *)[cell.contentView.subviews lastObject] removeFromSuperview];
}
}
Obj* obj = [_arr objectAtIndex:indexPath.row];
cell.textLabel.text = obj.name;
if (obj.icon) {
cell.imageView.image = obj.icon;
}else{
cell.imageView.image = [UIImage imageNamed:@"pleasehoder.png"];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSURL * url = [NSURL URLWithString:obj.url];
NSData * data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
obj.icon =[UIImage imageWithData:data] ;
cell.imageView.image = obj.icon;
});
});
}
// [self performSelector:@selector(loadImage:) withObject:indexPath afterDelay:0.f inModes:@[NSDefaultRunLoopMode]];
//[self loadImage:indexPath];
return cell;
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
NSArray *indexArray = [_tableview indexPathsForVisibleRows];
for (NSIndexPath * index in indexArray) {
UITableViewCell * cell = [_tableview cellForRowAtIndexPath:index];
Obj * obj = [_arr objectAtIndex:index.row];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSURL * url = [NSURL URLWithString:obj.url];
NSData * data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
if (!obj.icon) {
obj.icon =[UIImage imageWithData:data] ;
cell.imageView.image =obj.icon ;
}
});
});
}
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
if (!decelerate) {
NSArray *indexArray = [_tableview indexPathsForVisibleRows];
for (NSIndexPath * index in indexArray) {
UITableViewCell * cell = [_tableview cellForRowAtIndexPath:index];
Obj * obj = [_arr objectAtIndex:index.row];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSURL * url = [NSURL URLWithString:obj.url];
NSData * data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
if (!obj.icon) {
obj.icon =[UIImage imageWithData:data] ;
cell.imageView.image =obj.icon ;
}
});
});
}
}
}
@end
以上代码可以完成只加载手机上可见tableview的cell的内容,但是如果图片较多,且字节较大,可以观察app的memory会瞬间达到一个多G,这样太消耗内存。容易导致app闪退,所以要继续优化,也许你会说,可以让后台处理,但是如果是从手机相册选取的高清大图呢,所以客户端仍然需要处理,这就需要用到iOS的重绘了
//将大图重绘至画板
-(NSData*)useImage:(UIImage*)image {
//实现等比例缩放
CGFloat hfactor = image.size.width*1.0 / [UIScreenmainScreen].bounds.size.width;
CGFloat vfactor = image.size.height*1.0 / [UIScreenmainScreen].bounds.size.width;
CGFloat factor = (hfactor>vfactor) ? hfactor : vfactor;
//画布大小
CGFloat newWith = image.size.width*1.0 / factor;
CGFloat newHeigth = image.size.height*1.0 / factor;
CGSize newSize = CGSizeMake(newWith, newHeigth);
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newWith, newHeigth)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//图像压缩
NSData* newImageData = UIImageJPEGRepresentation(newImage, 0.5);
return newImageData;
}
将之前的这句代码 obj.icon =[UIImage imageWithData:data] ; 替换成
obj.icon =[UIImage imageWithData:[self useImage:[UIImage imageWithData:data]]] ;
你再测试下,内存也就是在100多M,比之前节省了十多倍的内存,加载大量图片,内存消耗在200M还是合理的。