美文网首页
利用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