美文网首页
利用Runloop优化下拉刷新TableView加载Image

利用Runloop优化下拉刷新TableView加载Image

作者: 红色海_ | 来源:发表于2020-03-29 19:39 被阅读0次
#import "ViewController.h"

@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UITableView *tableView;

@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, strong) NSMutableArray *tasks;
@property (nonatomic, assign) NSInteger maxTaskNumber;

@end

void callBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info){
    //C语言与OC的交换用到桥接 __bridge
    //处理控制器加载图片的事情
    ViewController *VC = (__bridge ViewController *)(info);
    if (VC.tasks.count == 0) {
        return;
    }
    void(^task)() = [VC.tasks firstObject];
    task();
    [VC.tasks removeObject:task];
    NSLog(@"COUNT:%ld",VC.tasks.count);
    
}

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    [self addRunloopOvserver];
    
    self.maxTaskNumber = 18;
    self.tasks = [NSMutableArray array];
    
    
    [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
    
}
-(void)timerMethod{
    
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    ViewController2 *vc2 = [ViewController2 new];
    [self presentViewController:vc2 animated:YES completion:^{
        
    }];
}

- (void)addRunloopOvserver{
    //获取当前的RunLoop
    CFRunLoopRef runloop = CFRunLoopGetCurrent();
    //上下文 (此处为C语言 对OC的操作需要上下文)将(__bridge void *)self 传入到Callback
    CFRunLoopObserverContext context = {0, (__bridge void *)self, &CFRetain, &CFRelease};
    //创建观察者 监听BeforeWaiting 监听到就调用回调callBack
    CFRunLoopObserverRef observer = CFRunLoopObserverCreate(NULL, kCFRunLoopBeforeWaiting, YES, 0, &callBack, &context);
    //添加观察者到当前runloop kCFRunLoopDefaultMode可以改为kCFRunLoopCommonModes
    CFRunLoopAddObserver(runloop, observer , kCFRunLoopCommonModes);
    //C语言中 有create就需要release
    CFRelease(observer);
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)p{
    return 30000;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identity" forIndexPath:indexPath];
    NSLog(@"---run---%@",[NSRunLoop currentRunLoop].currentMode);
    //以下两个循环的UI操作在必须放在主线程,但是弊端就是太多图片的处理会阻塞tableview的滑动流畅性
    for (int i = 1; i < 4; i++) {
        UIImageView *imageView = [cell.contentView viewWithTag:i];
        [imageView removeFromSuperview];
    }
    for (int i = 1; i < 4; i++) {
    /*
     阻塞模式
    */
    //        CGFloat leading = 10, space = 20, width = 103, height = 87, top = 15;
    //        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((i - 1) * (width + space) + leading, top, width, height)];
    //        [cell.contentView addSubview:imageView];
    //        imageView.tag = i;
    //        imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"image" ofType:@"png"]];

        
    
    //阻塞原因:kCFRunLoopDefaultMode时候 多张图片一起加载(耗时)loop不结束无法BeforeWaiting(即将进入休眠) 切换至UITrackingRunLoopMode来处理等候的UI刷新事件造成阻塞
    //解决办法:每次RunLoop循环只加载一张图片 这样loop就会很快进入到BeforeWaiting处理后面的UI刷新(UITrackingRunLoopMode 优先处理)或者没有UI刷新事件继续处理下一张图片
    
        /*
         流畅模式
        */
        //下面只是把任务放到数组 不消耗性能
        void(^task)() = ^{
            CGFloat leading = 10, space = 20, width = 103, height = 87, top = 15;
            UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((i - 1) * (width + space) + leading, top, width, height)];
            [cell.contentView addSubview:imageView];
            imageView.tag = i;
            imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"image" ofType:@"png"]];
        };
        [self.tasks addObject:task];
        //保证只拿最新的18个任务处理
        if (self.tasks.count > self.maxTaskNumber) {
            [self.tasks removeObjectAtIndex:0];
        }
    }
    return cell;
}



- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

相关文章

网友评论

      本文标题:利用Runloop优化下拉刷新TableView加载Image

      本文链接:https://www.haomeiwen.com/subject/hynuuhtx.html