当我们如果想要在cell中显示很多高清的大图片的时候如果一下子加载很多,肯定会有卡顿现象的产生,是一个耗时操作,我们可能会想着耗时操作的话就往子线程中扔,但是我们是在做UI的操作,所以我们不应该放到子线程中。这样的话我们应该考虑用Runloop,每次循环我们再去加载一张图片,这样的话卡顿结果就会解决,因为相比较一次循环加载多张图片肯定好很多。
首先我们应该去监听Runloop的状态,因为只有这样子,我们才能去进行相应的设置让每次睡眠前也就是说事情处理完即将进入休眠的时候再次去进行加载图片,这样的话我们就应该去监听的是达到kCFRunLoopBeforeWaiting这个状态应该做的事。大致步骤如下所示。
#import "ViewController.h"
//加载图片其实就是一段代码,我们可以放到block中,这样就可以把block放在数组里面,然后再去一个一个的去加载
typedef void(^loadBlock)(void);
@interface ViewController ()
@property (nonatomic ,strong)NSMutableArray *loadTasks;
@property(nonatomic,assign)CFRunLoopObserverRef observer;
//设置加载图片的最大的数量,因为如果我们滚动的tableView的速度很快的话。就会有很多加载图片的任务被添加进数组,但是我们显示的需要的图片是很少的所以要做个限制
@property (nonatomic,assign) int maxCount;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self addRunLoopObserver];
}
-(void)addRunLoopObserver
{
//1、先获取当前的Runloop
CFRunLoopRef runloop = CFRunLoopGetCurrent();
//定义观察者
CFRunLoopObserverRef observer;
CFRunLoopObserverContext context = {
0,
(__bridge void *)self,
&CFRetain,
&CFRelease,
NULL
};
//创建观察者 参数一:分配空间的方式,参数二:运行循环状态,参数三:是否一直监听,参数四:优先级 参数五:回调函数的地址,参数六:上下文
observer = CFRunLoopObserverCreate(kCFAllocatorMalloc, kCFRunLoopBeforeWaiting, YES, 0, &callout, &context);
//添加观察者,添加在common模式下面
CFRunLoopAddObserver(runloop, observer, kCFRunLoopCommonModes);
//使用添加任务的代码我们可以直接这么使用
[self addTask:^{
//加载图片的代码
[self loadImage];
}];
self.observer=observer;
//先移除观察者,如果不移除,观察者没有释放,控制器不会释放
CFRunLoopRemoveObserver(runloop, observer, kCFRunLoopCommonModes);
//释放观察者
CFRelease(observer);
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"%@",self.observer);
}
void callout(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
{
ViewController * vc = (__bridge ViewController *)info;
//表示没有任务就返回
if(vc.loadTasks.count==0)
{
return;
}
loadBlock task = vc.loadTasks.firstObject;
task();
[vc.loadTasks removeObjectAtIndex:0];
}
//就是在数组中添加block任务
-(void)addTask:(loadBlock)task
{
//还要判断下数组中的任务数量
if(self.loadTasks.count>_maxCount)
{
//也就是把最先的任务先删除掉,这样之前的Cell就不会再显示图片了
[self.loadTasks removeObjectAtIndex:0];
}
[self.loadTasks addObject:task];
}
//加载图片的操作
-(void)loadImage
{
}