8、RunLoop

学习博客:http://blog.ibireme.com/2015/05/18/runloop/
学习视频一:http://my.tv.sohu.com/pl/9137530/84240913.shtml
学习视屏二:http://my.tv.sohu.com/us/240760748/84240914.shtml
一、RunLoop简单概述
1)运行循环
内部实现:内部是由do-while循环实现的;
2)RunLoop作用
1、保证程序的持续运行;
2、处理APP的各种事件(滑动,定时器,selector);
3、节省cpu资源,提高程序性能;
3)RunLoop与线程
1、每条线程都有唯一的一个与之对应的RunLoop对象;
2、主线程的RunLoop随着程序已自动创建好,但是子线程的RunLoop需要手动创建;
3、获得主线程的RunLoop的方法是[NSRunLoop mainRunLoop];
4、创建子线程的RunLoop方法是[NSRunloop currentRunLoop];
***苹果不允许创建RunLoop,只是提供上述两种获得RunLoop的方法;
4)CFRunLoop的结构如下:

  struct __CFRunLoop {
    CFMutableSetRef _commonModes;     // Set
    CFMutableSetRef _commonModeItems; // Set<Source/Observer/Timer>
    CFRunLoopModeRef _currentMode;    // Current Runloop Mode
    CFMutableSetRef _modes;           // Set
    ...
};

这里有个概念叫“CommonModes”:一个mode可以将自己标记为“Common”属性(通过将其ModeName添加到RunLoop的“commonModes”中)。每当RunLoop的内容发生变化时,RunLoop都会自动将_commonModeItems里的Source/Timer/Observer同步到具有“Common”标记的所有Mode里;
应用场景举例:主线程的RunLoop里有两个预设置的Mode:kCFRunLoopDefaultMode和UITrackingRunLoopMode。这两个Mode都已经被标记为“Common”属性。DefaultMode是APP平时所处的状态,TrackingRunLoopMode是追踪ScrollView滑动时的状态。当你创建一个Timer并加到DefaultMode时,Timer会得到重复回调,但此时滑动一个TableView时,RunLoop会将Mode切换为TrackingRunLoopMode,这时Timer就不会被回调,并且也不会影响到滑动操作;
有时需要一个Timer,在两个Mode钟都能得到回调,一种办法就是将这个Timer分别加入到这两个Mode钟。还有一种方式,就是讲Timer加入到顶层的RunLoop的NSRunLoopCommonModes中。commonModeItems被自动更新到所有具有“Common”属性的Mode里去;

二、RunLoop相关类
1、CFRunLoopModeRef
2、CFRunLoopSourceRef
3、CFRunLoopTimerRef
4、CFRunLoopObserverRef

1、一个RunLoop包含若干个Mode,每个Mode又包含若干个Source/Timer/Observer。每次调用RunLoop的主函数时,只能指定其中一个Mode,这个Mode被称作CurrentMode。如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入。这样做主要是为了分隔开不同组的Source/Timer/Observer,让其互不影响;
CFRunLoopMode的结构大致如下:

 struct __CFRunLoopMode {
    CFStringRef _name;            // Mode Name
    CFMutableSetRef _sources0;    // Set
    CFMutableSetRef _sources1;    // Set
    CFMutableArrayRef _observers; // Array
    CFMutableArrayRef _timers;    // Array
    ...
};

系统默认注册的5个Mode
1)kCFRunLoopDefaultMode:主线程在该Mode下运行;
2)UITrackingRunLoopMode:界面跟踪Mode,用于scrollView追踪触摸滑动,保证界面滑动时,不收其它Mode影响;
3)UIInitializationRunLoopMode:刚启动时APP进入的第一个Mode,启动完成后就不再使用;
4)GSEvenReceiveRunLoopMode:接受系统事件的内部Mode,通常情况不用;
5)kCFRunLoopCommonModes:占位用的Mode,不是真正的Mode;

2、CFRunLoopSourceRef是事件源,也称输入员;
官方文档分类:
1)Port-Based Sources 从其他线程或内核发出的;

  1. Custom Input Sources 自定义的;
  2. CoCoa Perform Selector Sources

按函数调用栈分类,可分为2类;
Source有两个版本:Source0和Source1.
Source0,非基于Port的,只包含了一个回调(函数指针),它并不能主动触发事件。使用时,你需要先调用CFRunLoopSourceSigna(source),将这个Source标记为待处理,然后手动调用CFRunLoopWakeUp(runloop)来唤醒RunLoop,让其处理这个事件;
Source1,基于Port的,包含了一个mach_port和一个回调(函数指针),被用于通过内核和其它线程相互发送消息。这种Source能主动唤醒RunLoop的线程;

3、CFRunLoopTimerRef是基于时间的触发器,它和NSTimer是toll-free bridged的,可以混用。其包含一个时间长度和一个回调(函数指针).当其加入到RunLoop时,RunLoop会注册对应的时间点,当时间点到时,RunLoop会被唤醒以执行那个回调;

4、CFRunLoopObserverRef是观察者,每个Observer都包含了一个回调(函数指针),当RunLoop的状态发生变化时,观察者能通过回调接收到这个变化。可以观测的时间点有以下几个:

 typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry         = (1UL << 0), // 即将进入Loop
    kCFRunLoopBeforeTimers  = (1UL << 1), // 即将处理 Timer
    kCFRunLoopBeforeSources = (1UL << 2), // 即将处理 Source
    kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
    kCFRunLoopAfterWaiting  = (1UL << 6), // 刚从休眠中唤醒
    kCFRunLoopExit          = (1UL << 7), // 即将退出Loop
 kCFRunLoopAllActivities = OxOFFFFFFFU // 活跃中
};

上面的Source/Timer/Observer被统称为mode item,一个item可以被同时加入多个mode。但一个item被重复加入同一个mode时是不会有效果的。如果一个mode中一个item都没有,则RunLoop会直接退出,不进入循环;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容