iOS RunLoop 的 Mode
来源:互联网 发布:学白话软件 编辑:程序博客网 时间:2024/04/28 14:53
//// ViewController.m// test_runloop_01//// Created by jeffasd on 16/7/25.// Copyright © 2016年 jeffasd. All rights reserved.//#import "ViewController.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; //苹果公开提供的 Mode 有两个:kCFRunLoopDefaultMode (NSDefaultRunLoopMode) 和 UITrackingRunLoopMode,你可以用这两个 Mode Name 来操作其对应的 Mode。 [[NSRunLoop currentRunLoop] runMode:UITrackingRunLoopMode beforeDate:[NSDate distantFuture]]; [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; //同时苹果还提供了一个操作 Common 标记的字符串:kCFRunLoopCommonModes (NSRunLoopCommonModes),你可以用这个字符串来操作 Common Items,或标记一个 Mode 为 "Common"。使用时注意区分这个字符串和其他 mode name。 //commonModeItems //这里使用的模式是:NSRunLoopCommonModes,这个模式等效于NSDefaultRunLoopMode和NSEventTrackingRunLoopMode的结合。 //运行在此模式下 commonModeItems 内 每当 RunLoop 的内容发生变化时,RunLoop 都会自动将 commonModeItems 里的 Source/Observer/Timer 同步到具有 "Common" 标记的所有Mode里。由于主线程的 RunLoop 里有两个预置的 Mode:kCFRunLoopDefaultMode 和 UITrackingRunLoopMode。这两个 Mode 都已经被标记为"Common"属性。 //所以NSRunLoopCommonModes此模式会处理 来自UITrackingRunLoopMode和NSDefaultRunLoopMode内的时间 [[NSRunLoop currentRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate distantFuture]]; NSTimer *timer = nil; //将 Timer 加入到顶层的 RunLoop 的 "commonModeItems" 中。"commonModeItems" 被 RunLoop 自动更新到所有具有"Common"属性的 Mode 里去。 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; }- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end
a 主线程的runloop自动创建,子线程的runloop默认不创建(在子线程中调用NSRunLoop *runloop = [NSRunLoop currentRunLoop];获取RunLoop对象的时候,就会创建RunLoop);b runloop退出的条件:app退出;线程关闭;设置最大时间到期;modeItem为空;c 同一时间一个runloop只能在一个mode,切换mode只能退出runloop,再重进指定mode(隔离modeItems使之互不干扰);d 一个item可以加到不同mode;一个mode被标记到commonModes里(这样runloop不用切换mode)。
RunLoop 的 Mode
CFRunLoopMode 和 CFRunLoop 的结构大致如下:
struct __CFRunLoopMode {
CFStringRef _name;
// Mode Name, 例如 @"kCFRunLoopDefaultMode"
CFMutableSetRef _sources0;
// Set
CFMutableSetRef _sources1;
// Set
CFMutableArrayRef _observers;
// Array
CFMutableArrayRef _timers;
// Array
...
};
struct __CFRunLoop {
CFMutableSetRef _commonModes;
// Set
CFMutableSetRef _commonModeItems;
// Set
CFRunLoopModeRef _currentMode;
// Current Runloop Mode
CFMutableSetRef _modes;
// Set
...
};
这里有个概念叫 "CommonModes":一个 Mode 可以将自己标记为"Common"属性(通过将其 ModeName 添加到 RunLoop 的 "commonModes" 中)。每当 RunLoop 的内容发生变化时,RunLoop 都会自动将 _commonModeItems 里的 Source/Observer/Timer 同步到具有 "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 的 "commonModeItems" 中。"commonModeItems" 被 RunLoop 自动更新到所有具有"Common"属性的 Mode 里去。
CFRunLoop对外暴露的管理 Mode 接口只有下面2个:
CFRunLoopAddCommonMode(CFRunLoopRef runloop, CFStringRef modeName);
CFRunLoopRunInMode(CFStringRef modeName, ...);
Mode 暴露的管理 mode item 的接口有下面几个:
CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef modeName);
CFRunLoopAddObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFStringRef modeName);
CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef timer, CFStringRef mode);
CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef modeName);
CFRunLoopRemoveObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFStringRef modeName);
CFRunLoopRemoveTimer(CFRunLoopRef rl, CFRunLoopTimerRef timer, CFStringRef mode);
你只能通过 mode name 来操作内部的 mode,当你传入一个新的 mode name 但 RunLoop 内部没有对应 mode 时,RunLoop会自动帮你创建对应的 CFRunLoopModeRef。对于一个 RunLoop 来说,其内部的 mode 只能增加不能删除。
苹果公开提供的 Mode 有两个:kCFRunLoopDefaultMode (NSDefaultRunLoopMode) 和 UITrackingRunLoopMode,你可以用这两个 Mode Name 来操作其对应的 Mode。
同时苹果还提供了一个操作 Common 标记的字符串:kCFRunLoopCommonModes (NSRunLoopCommonModes),你可以用这个字符串来操作 Common Items,或标记一个 Mode 为 "Common"。使用时注意区分这个字符串和其他 mode name。
参考文章:http://www.jianshu.com/p/37ab0397fec7
http://www.cocoachina.com/ios/20150601/11970.html
- iOS RunLoop 的 Mode
- iOS 面试题~RunLoop和线程的关系?runloop的mode作用是什么?
- NSURLConnection的default runloop mode
- runloop的mode作用是什么
- runloop 的 mode 作用是什么
- iOS 的RunLoop初识
- ios runloop的初探
- 认识iOS的RunLoop
- 深入理解IOS的RunLoop
- iOS RunLoop 自己的理解
- iOS RunLoop 的个人理解
- iOS runloop 详解3 如何停止子线程的runloop
- iOS runloop
- iOS runloop
- iOS RunLoop
- iOS runloop
- <iOS>RunLoop
- iOS RUNLOOP
- PHP木马的防范方法
- 合并果子解题分析
- Java反射机制的学习
- AsyncTask的使用
- 滴滴的程维应该是幸福的
- iOS RunLoop 的 Mode
- ExtJs6 时间转换为'x天','x小时','x分','x秒前'并且鼠标移上去悬浮提示具体时间
- JavaScript encodeURI() 函数详解
- Linux内核---58.kthread与wait_event
- Android 拷贝assets目录下所有文件及文件夹到指定路径
- 详解并行逻辑回归
- hdu 2094
- 三角数数列
- Linux内核---59.netlink应用层与内核层的交互