运行循环在表视图中的应用

本代码仿照国外开发者写的方法TableView流畅加载高清无码大图 , 创建Runloop每次只执行一张大图!
三张大图都是很大的桌面图:

运行循环在表视图中的应用_第1张图片
Batman.jpg
运行循环在表视图中的应用_第2张图片
Joker.jpg
运行循环在表视图中的应用_第3张图片
Joker1.jpg

效果如下请看gif图:

  • 首先看一下不使用RunLoop的情况,真的是非常慢!!!


    不使用RunLoop的情况.gif
  • 再看一下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

愿编程让这个世界更美好

你可能感兴趣的:(运行循环在表视图中的应用)