本代码仿照国外开发者写的方法TableView流畅加载高清无码大图 , 创建Runloop每次只执行一张大图!
三张大图都是很大的桌面图:
效果如下请看gif图:
-
首先看一下不使用RunLoop的情况,真的是非常慢!!!
-
再看一下RunLoop添加之后的情况 , 很流畅 ! 但是怎么老有空的?!应该是我代码没写完整.....但是思路没有错!!!
ViewController.m文件
#import "ViewController.h"
//定义一个代码块封装添加图片和文字的整个一套方法:
typedef void (^RunloopBlock) (void) ;
static NSString *const MD_IDENTIFIER = @"MD_IDENTIFIER" ;
static NSInteger const CELL_Height = 135.f ;
@interface ViewController ()
@property (nonatomic , strong) UITableView *MD_TableView ;
//定义一个事件出来:
@property (nonatomic , strong) NSTimer *timer ;
//定义一个数组来放block代码块任务:
@property (nonatomic , strong) NSMutableArray *taskArray ;
//从数组中取出最后的6个cell钟的18张图片(最大任务数)(最大队列长度):
@property (nonatomic , assign) NSInteger maxQueueLength ;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.MD_TableView = [[UITableView alloc] initWithFrame:self.view.bounds] ;
self.MD_TableView.delegate = self ;
self.MD_TableView.dataSource = self ;
[self.MD_TableView registerClass:[UITableViewCell class] forCellReuseIdentifier:MD_IDENTIFIER] ;
[self.view addSubview:self.MD_TableView] ;
self.timer = [NSTimer scheduledTimerWithTimeInterval:.001 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES] ;
self.taskArray = [NSMutableArray array] ;
self.maxQueueLength = 18 ;
//添加Runloop的观察者方法:
[self addRunloopObserver] ;
}
//这里面不做事情 , 目的是让Runloop循环一直跑起来!
- (void)timerMethod {
NSLog(@"方法名: %s , 行数: %zd" , __FUNCTION__ , __LINE__) ;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated] ;
self.MD_TableView.frame = self.view.frame ;
}
#pragma mark - cell内部方法
+ (void)addLabelForCell:(UITableViewCell *)cell andIndexPath:(NSIndexPath *)indexPath {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 300, 25)] ;
label.backgroundColor = [UIColor clearColor] ;
label.textColor = [UIColor redColor] ;
label.text = [NSString stringWithFormat:@"%zd - Joker大图", indexPath.row] ;
label.font = [UIFont boldSystemFontOfSize:13] ;
label.tag = 4 ;
[cell.contentView addSubview:label] ;
UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(5, 99, 300, 35)];
label1.lineBreakMode = NSLineBreakByWordWrapping ;
label1.numberOfLines = 0 ;
label1.backgroundColor = [UIColor clearColor] ;
label1.textColor = [UIColor colorWithRed:0 green:100.f/255.f blue:0 alpha:1] ;
label1.text = [NSString stringWithFormat:@"%zd - Batman大图.", indexPath.row] ;
label1.font = [UIFont boldSystemFontOfSize:13] ;
label1.tag = 5;
[cell.contentView addSubview:label1] ;
}
#pragma mark - 加载第 1 张图片
+ (void)addImage1WithCell:(UITableViewCell *)cell {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(5, 20, 85, 85)] ;
imageView.tag = 1 ;
NSString *path = [[NSBundle mainBundle] pathForResource:@"Joker" ofType:@"jpg"] ;
UIImage *image = [UIImage imageWithContentsOfFile:path] ;
imageView.contentMode = UIViewContentModeScaleAspectFit ;
imageView.image = image ;
[UIView transitionWithView:cell.contentView duration:.1 options:(UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve) animations:^{
[cell.contentView addSubview:imageView] ;
} completion:nil] ;
}
#pragma mark - 加载第 2 张图片
+ (void)addImage2WithCell:(UITableViewCell *)cell {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(105, 20, 85, 85)] ;
imageView.tag = 2 ;
NSString *path = [[NSBundle mainBundle] pathForResource:@"Batman" ofType:@"jpg"] ;
UIImage *image = [UIImage imageWithContentsOfFile:path] ;
imageView.contentMode = UIViewContentModeScaleAspectFit ;
imageView.image = image ;
[UIView transitionWithView:cell.contentView duration:.1 options:(UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve) animations:^{
[cell.contentView addSubview:imageView] ;
} completion:nil] ;
}
#pragma mark - 加载第 3 张图片
+ (void)addImage3WithCell:(UITableViewCell *)cell {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(205, 20, 85, 85)] ;
imageView.tag = 3 ;
NSString *path = [[NSBundle mainBundle] pathForResource:@"Joker1" ofType:@"jpg"] ;
UIImage *image = [UIImage imageWithContentsOfFile:path] ;
imageView.contentMode = UIViewContentModeScaleAspectFit ;
imageView.image = image ;
[UIView transitionWithView:cell.contentView duration:.1 options:(UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve) animations:^{
[cell.contentView addSubview:imageView] ;
} completion:nil] ;
}
#pragma mark -
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 200 ;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MD_IDENTIFIER] ;
cell.selectionStyle = UITableViewCellSelectionStyleNone ;
//删除cell上面已经流出的子控件 , 节约内存:
for (NSInteger i = 1; i <= 5; i++) {
[[cell.contentView viewWithTag:i] removeFromSuperview] ;
}
[self addTask:^{
//添加Label:
[ViewController addLabelForCell:cell andIndexPath:indexPath] ;
}] ;
[self addTask:^{
[ViewController addImage1WithCell:cell] ;
}] ;
[self addTask:^{
[ViewController addImage2WithCell:cell] ;
}] ;
[self addTask:^{
[ViewController addImage3WithCell:cell] ;
}] ;
return cell ;
}
#pragma mark -
//定义一个回调函数:
static void callBack(CFRunLoopObserverRef observer , CFRunLoopActivity activity , void *info) {
ViewController *VC = (__bridge ViewController *)(info) ;
if (VC.taskArray.count == 0) {
return ;
} else {
RunloopBlock task = VC.taskArray.firstObject ;
//执行任务:
task() ;
//删除执行完毕后的任务:
[VC.taskArray removeObjectAtIndex:0] ;
}
}
- (void)addRunloopObserver {
//获取当前的Runkoop:
CFRunLoopRef runloop = CFRunLoopGetCurrent() ;
//定义一个观察者:
static CFRunLoopObserverRef defaultModeObserver ;
//定义一个上下文:
//这是一个C语言结构体:
CFRunLoopObserverContext context = {
0,
(__bridge void *)self,
&CFRetain,
&CFRelease,
NULL
} ;
//创建观察者:
defaultModeObserver = CFRunLoopObserverCreate(NULL, kCFRunLoopBeforeWaiting, YES, 0, callBack, &context) ;
//把观察者添加为Runloop的观察者:
CFRunLoopAddObserver(runloop, defaultModeObserver, kCFRunLoopDefaultMode) ;
//C语言需要release释放create指针:
CFRelease(defaultModeObserver) ;
}
#pragma mark - 添加任务的方法
- (void)addTask:(RunloopBlock)task {
[self.taskArray addObject:task] ;
if (self.taskArray.count > _maxQueueLength) {
[self.taskArray removeObjectAtIndex:0] ;
}
}
#pragma mark -
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return CELL_Height ;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end