NSRunLoop学习笔记
来源:互联网 发布:淘宝网店服装头像图片 编辑:程序博客网 时间:2024/05/21 10:05
内容是自己学习笔记,来源于互联网
RunLoop简介
基本作用
- 保持程序的持续运行,相当于一个do while循环,程序相当于一个死循环,一直在循环内做事情。程序启动时已经启动了一个runLoop,所以程序不会直接退出。是在main函数启动的,和主线程相关.
- 处理APP的各种事件:触摸,定时器,selector事件,事件触发的时候,runLoop会按步骤执行事件。
- 节省CPU的资源,提升程序性能,合理分配工作和休眠时间,在没有操作任务的时候会进入休眠,有任务到来会唤醒.
runLoop对象
iOS 两套方案访问runLoop
- Foundation -> NSRunLoop
- Core Foundation -> CFRunLoopRef
NSRunLoop和CFRunLoopRef都代表RunLoop对象。NSRunLoop是基于CFRunLoopRef的一层OC的包装,CFRunLoopRef是RunLoop底层API.
RunLoop与线程的关系
- 每条线程都有唯一的一个与之对应的RunLoop对象.
- 主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建
- RunLoop 在第一次获取时候创建,在线程结束时候销毁.
获取RunLoop对象的方法
Foundation
[NSRunLoop mainRunLoop]; [NSRunLoop currentRunLoop];
CFRunLoopRef
CFRunLoopGetCurrent();CFRunLoopGetMain();
RunLoop相关类
CFRunLoopRef ;// CFRunLoopSourceRef;//sourceCFRunLoopTimerRef;//定时器CFRunLoopObserverRef;//观察者CFRunLoopModeRef;//这个类没有外漏
CFRunLoopModeRef
CFRunLoopModeRef表示RunLoop的运行模式.
- 一个RunLoop可以包含若干个Mode,一个Mode 包含不同的若干个source,timer,observer。
- 每次RunLoop启动只能指定其中一种模式,可以通过curreMode方法获取
- 切换mode只能退出Loop,重新再指定一个Mode进入,这样可以分开不同模式下的source,timer,observer
CFRunLoopModeRef以供有5个,其中有两个用不到一个是UIInitializationRunLoopMode 是刚刚进入程序的时候进入的第一个,启动完成后就退出了,还有一个GSEventReceiveRunLoopMode,是系统内部的,也用不到,而且代码根本打不出来,所以可以忽略.
kCFRunLoopCommonModes; //kCFRunLoopDefaultMode|UITrackingRunLoopModekCFRunLoopDefaultMode;//默认模式,app启动后的模式,主线程就是这个模式 UITrackingRunLoopMode;//界面跟踪模式,追踪触屏滑动,保证界面滑动时候不受其他mode影响
CFRunLoopSourceRef
CFRunLoopSourceRef表示的是事件的输入源。
分类1:
- Port-Based Source 基于端口的,内核或者其他线程发过来的信息
- Custom Input Source 自定义的,一般不用
- Cocoa perform selector sources 通过selector消息选择器发送的事件
分类2:
- source0 :非基于port的
- source1 :基于内核的和其他线程通信,接受分发系统事件.
CFRunLoopTimerRef
就是NSTimer,定时器.
CFRunLoopObserverRef
可以监听状态runLoop状态变化的观察者.监听runLoop包含下面的状态
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) { kCFRunLoopEntry = (1UL << 0),//进入runLoop kCFRunLoopBeforeTimers = (1UL << 1),//即将处理timer事件 kCFRunLoopBeforeSources = (1UL << 2),//即将处理source kCFRunLoopBeforeWaiting = (1UL << 5),//即将进入休眠 kCFRunLoopAfterWaiting = (1UL << 6),//刚从休眠中唤醒 kCFRunLoopExit = (1UL << 7),//runLoop退出了 kCFRunLoopAllActivities = 0x0FFFFFFFU//所有的状态};
runLoop处理逻辑
官方版本
网络版本
runLoop应用
定时器
NSTimer定时器的创建方式
第一种:
// 调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopModeNSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];// 修改模式[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
第二种:创建一个纯净的定时器,需要自己手动设置运行模式
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];// 定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作// [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];// 定时器只运行在UITrackingRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作// [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];// 定时器会跑在标记为common modes的模式下// 标记为common modes的模式:UITrackingRunLoopMode和NSDefaultRunLoopMode[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
在runLoop状态变化时候做事情
// 创建observer//第一个参数表示如何给observe分配空间,CFAllocatorGetDefault,表示用默认的空间分配器//第二个参数表示监听的是什么状态,可以检测一种也可以检测所有的//YES 表示不是监听一次,而是每次通过这个runLoop的时候都监听//0 位置的参数表示设定优先级,用于多个观察者同时监听一个runLoop的时候,数字越小,优先级越高,默认写0就可以了//后面的块,可以打印相关的状态CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopBeforeWaiting, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { NSLog(@"----监听到RunLoop状态发生改变---%zd", activity);});// 添加观察者:监听RunLoop的状态//第一个参数.获取添加观察者的runLoop//第二个参数.添加观察者对象//第三个参数.要监听的模式CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);// 释放ObserverCFRelease(observer);
imageView显示
// 只在NSDefaultRunLoopMode模式下显示图片[self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"placeholder"] afterDelay:3.0 inModes:@[NSDefaultRunLoopMode]];
可以解决tableView或者scrollView滑动时候卡顿问题,让图片仅仅在不滑动的时候加载.提升用户体验.
创建不死线程
默认状态下线程执行完操作就死亡了,要创建一个不死线程要用runLoop。
实现策略:
创建一个线程:
self.thread = [[XMGThread alloc] initWithTarget:self selector:@selector(run) object:nil];[self.thread start];
在线程的run方法里面,添加代码启动新创建的线程的runLoop,
runLoop的run方法,运行的时候如果发现运行模式为空会直接退出,
runLoop不可以没有source,timer,observer.如果3个都没有,就会退出.
所以必须要添加一个保证不退出。
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];[[NSRunLoop currentRunLoop] run];
调用run方法相当下面的情况的一种,都是一致运行到一个非常大的日期,保证不会退出.创造一个死循环.
// [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];// [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
runLoop循环,不会像do while循环卡死,而是一致在不断的运行着,只有当事件触发的时候才会响应时间,没有事件就会休眠.
- NSRunLoop学习笔记
- IOS多线程编程笔记与NSRunLoop学习
- NSOperationQueue、NSRunLoop和线程安全 学习笔记
- NSRunLoop 学习
- NSRunloop学习
- NSRunLoop
- nsrunloop
- NSRunloop
- nsrunloop
- NSRunLoop
- NSRunloop
- NSRunLoop
- NSRunLoop
- NSRunLoop
- NSRunLoop
- NSRunLoop
- NSRunLoop
- NSRunLoop
- Kafka入门经典教程
- wincc 动态图片的集中实现办法
- 每一天都感觉自己在进步。
- linux 命令
- mac 安装使用Liteide
- NSRunLoop学习笔记
- poj2441 Arrange the Bulls 状压DP
- win7下vs2010的Visual Assist X插件过期后永久激活方法
- C# 汉字转拼音(支持GB2312字符集中所有汉字)
- ytu1402: 1.1.2 Greedy Gift Givers 贪婪的送礼者
- Hbase完全分布式配置
- springMVC 和 struts2区别
- iOS中根据已有经纬度定位并显示在地图上
- hdu 5635 LCP Array(BC第一题)