#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];
}
网友评论