运行循环
//main.m
int main(int argc, char * argv[])
{
@autoreleasepool
{
int a = UIApplicationMain(argc, argv ,nil ,NSStringFromClass([AppDelegate class]));
NSLog(@"打印"); // 这个log不会打印。因为运行循环是个死循环,所以应用不会退出
return a;
}
}
//main.m
int main(int argc, char * argv[])
{
@autoreleasepool
{
NSLog(@"%@",[NSThread currentThread]); // runloop 保证线程不退出
int a = UIApplicationMain(argc, argv ,nil ,NSStringFromClass([AppDelegate class]));
// UIApplicationMain 会开启runloop
NSLog(@"打印");
return a;
}
}
1、作用:
- 保证runloop所在线程不退出
- 负责监听事件(触摸、时钟、网络)
- (void)viewDidLoad
{
[super viewDidLoad];
// 创建Timer
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
// 将Timer 添加到RunLoop
[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
}
- (void)timerMethod
{
NSLog(@"+1s");
}
/* 笔记:
可以正常循环打印
在滑动scrollview的时候timer暂停打印,不响应
原因:
ui模式的优先级最高,导致默认模式下的timer不被处理
*/
2、runloop的5种模式
-
默认模式
当默认模式中有事件需要处理,runloop将被唤醒,来处理默认模式中的事件,处理完后runloop继续进入休眠状态
-
UI模式
优先级最高,只能被ui事件唤醒,当ui模式有事件需要处理,runloop优先处理ui模式中的事件,其他模式中的事件就先不处理
- (void)viewDidLoad
{
[super viewDidLoad];
// 创建Timer
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
// 将Timer 添加到RunLoop
/*
UITrackingRunLoopMode - UI模式
*/
[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
}
- (void)timerMethod
{
NSLog(@"+1s");
}
/* 笔记:
没有ui操作的情况下不打印
在滑动scrollview的时候timer响应,开始打印
原因:
ui模式只能被ui事件唤醒
*/
-
占位模式(UI+默认) - NSRunLoopCommonModes
- (void)viewDidLoad { [super viewDidLoad]; // 创建Timer NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES]; // 将Timer 添加到RunLoop [NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; } - (void)timerMethod { NSLog(@"+1s"); } /* 笔记: 没有ui操作的情况下 和 在滑动scrollview的时候 timer都会响应,开始打印 原因: timer被添加进NSRunLoopCommonModes相当于timer同事被添加进默认模式和ui模式 */
3、子线程中的runloop
- (void)viewDidLoad
{
[super viewDidLoad];
NSTread *thread = [[NSThread alloc] initWithBlock:^{
// 创建Timer
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
// 将Timer 添加到RunLoop
[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
NSLog(@"子线程中%@",[NSTread currentThread]); // 会打印
}];
// start
[thread start];
}
// 注:如果此时线程对象没被销毁,其线程也被销毁了,如果想保住线程的命,要么是线程中的任务没有执行完
- (void)timerMethod
{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"timer%@",[NSTread currentThread]); // 不会打印
}
注:
如果此时线程对象没被销毁,其线程也被销毁了,如果想保住线程的命,要么是线程中的任务没有执行完,要么开启runloop
每条线程内部都有一个runloop,但是默认都不开启
- (void)viewDidLoad
{
[super viewDidLoad];
NSTread *thread = [[NSThread alloc] initWithBlock:^{
// 创建Timer
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
// 将Timer 添加到RunLoop
[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
// --重点--
[[NSRunLoop currentRunLoop] run];//手动开启当前线程的runloop
// --重点--
NSLog(@"子线程%@",[NSTread currentThread]); // 不会打印,因为上面的runloop相当于死循环
}];
// start
[thread start];
}
// 注:如果此时线程对象没被销毁,其线程也被销毁了,如果想保住线程的命,要么是线程中的任务没有执行完
- (void)timerMethod
{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"timer%@",[NSTread currentThread]); // 会打印
}
4、source - 事件源
类型:
按照函数调用栈划分:
-
source0
非source1
-
source1
系统内核事件
5、observer - 监听runloop循环
- (void)addRunloopObserver
{
//获取runloop
CFRunLoopRef runloop = CFRunLoopGetCurrent();
// 定义观察者
static CFRunLoopObserverRef defaultModeObserver;
// 创建上下文
CFRunLoopObserverContext context = {
0,
(__bridge void *)(self),
&CFRetain,
&CFRelease,
NULL
};
// 创建
defaultModeObserver = CFRunLoopObserverCreate(NULL, kCFRunLoopBeforeWaiting, 0, &CallBack, &context);
// 添加到当前runloop中
CFRunLoopAddObserver(runloop, defaultModeObserver , kCFRunLoopDefaultMode);
}
void CallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
{
NSLog(@"回调");
ViewController *vc = (__bridge ViewController *)info;
}