博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IOS多线程学习八:RunLoop
阅读量:3731 次
发布时间:2019-05-22

本文共 3625 字,大约阅读时间需要 12 分钟。

文章目录

概述

1.字面意思:运行循环

2.内部实现:内部是由do-while循环实现的

作用

1.保证程序的持续运行

2.处理APP的各种事件(滑动,定时器,selector)
3.节省CPU资源,提高程序性能,让线程有事情做的时候做,没事的时候处于休眠状态。

如果没有RunLoop

以main函数入口为例:

int main(int argc,char *argv[]){NSLog(@"execute main function");//程序开始return 0;//程序结束}

类似于oc程序,执行完相应的代码之后,程序杀死,不能保证APP的持续运行。

如果有RunLoop

以main函数入口为例

int main(int argc, char *argv[]){do{     NSLog(@"execute main function");//程序开始}while(1)return 0;//程序结束}相当于程序内部有一个死循环,保证程序运行不会中断。

main函数中的RunLoop

int main(int argh, char *argv[]){   @autoreleasepool{     return UIApplicationMain(argc,argv,nil,NSStringFromClass([AppDelegate class]));  }}

在UIApplicationMain函数内部就启动了一个RunLoop,所以UIApplicationMain函数就一直没有返回,保证了程序的持续运行。默认启动的RunLoop是跟主线程相关联的,主要处理与主线程相关的事件。

RunLoop循环图

在这里插入图片描述

线程执行,如果有事件,runloop就提醒线程来处理事件,如果没有事情做,线程处于一个休眠状态直到有操作进入,再提醒线程去做哪些事情,一直处于这种循环中。

RunLoop对象

iOS中有2套API来访问和使用RunLoop

  • Fundation NSRunLoop (OC语言的)
  • Core Foundation CFRunLoopRef (C语言的)
    都代表RunLoop,其间的联系是NSRunLoop是基于CFRunLoopRef。

RunLoop与线程

1.每条线程都有唯一的一个与之对应的RunLoop对象。

2.主线程的RunLoop随着程序已自动创建好,但是子线程的RunLoop需要手动创建。
3.获得主线程的RunLopp的方法是[NSRunLoop mainRunLoop];
4.获得子线程的RunLoop的方法是[NSRunLoop currentRunLoop];
注意:苹果不允许创建RunLoop,只提供了上述两种获得RunLoop的方法。

RunLoop相关类

1.CFRunLoopModeRef

2.CFRunLoopSourceRef
3.CFRunLoopTimeRef
4.CFRunLoopObserverRef
若没有以上几个类,RunLoop是不会循环的。
在这里插入图片描述

CFRunLoopModeRef

1.代表RunLoop的运行模式。

2.一个RunLoop可以包含若干个mode,每个mode包含若干个Source/Timer/Observer
3.每次RunLoop启动时,只能指定其中的一个Mode,这个Mode被称为currentMode
4.如果需要切换Mode,需要退出RunLoop,再重新指定一个Mode进入。这样做的原因是为了分离不同组Source/Timer/Observer,让其互不影响。
系统注册了5个Mode
1.kCFRunLoopDefaultMode:APP默认Mode,通常主线程是在该Mode下运行的
2.UITrackingRunLoopMode:界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时,不受其他mode影响
3.UIInitializationRunLoopMode:在刚启动时App进入的第一个Mode,启动完成后就不再使用。
4.GSEventReceiveRunLoopMode:接受系统事件的内部Mode,通常情况下不用。
5.kCFRunLoopCommonMode:这是一个占位的Mode,不是真正的Mode。

CFRunLoopTimerRef

基于时间的触发器,基本可以说是NSTimer。

//自动加在runloop下,可以直接运行    // [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
NSTimer *timer=[NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];    //只应用于默认模式下    //[[NSRunLoop currentRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];    //只应用于UITrackingRunLoopMode    //[[NSRunLoop currentRunLoop]addTimer:timer forMode:UITrackingRunLoopMode];    //应用于2种模式下,commonmodes是模式的标记,有这个标记的模式有UITrackingRunLoopMode, NSDefaultRunLoopMode。    2种模式有共同的标志,只要把这个标志写上,那么2种模式下都能运行。    [[NSRunLoop currentRunLoop]addTimer:timer forMode:NSRunLoopCommonModes];

CFRunLoopSourceRef

CFRunLoopSourceRef 是事件源,也可称为输入源。

1.Port-Based Sources 从其他线程或内核发出的。

2.Custom Input Sources自定义的。(很少用到)
3.CoCoa Perform Selector Sources. (常用)

按函数调用栈分类,可分为2类

1.Sources :非基于Port的,常见,比如点击事件
2.Sources1:基于Port的,通过其他线程或者内核通信,接受,分发系统事件。
调用栈其实是栈的一种抽象概念,它表示了方法之间的调用关系。
在这里插入图片描述

[self performSelector:@selector(run) withObject:nil afterDelay:2 inModes:@[NSRunLoopCommonModes]];

CFRunLoopObserverRef

观察者,能够监听RunLoop的状态的改变。

typedef CF_OPTIONS(CFOptionFlags,CFRunLoopActivity){
kCFRunLoopEntry=(1UL<<0),即将进入RunLoop
kCFRunLoopBeforeTimers=(1UL<<1),//即将处理Timer
kCFRunLoopBeforeSources=(1UL<<2),//即将处理Sources
kCFRunLoopBeforeWaiting=(1UL<<5),//即将进入休眠 2的5次方
kCFRunLoopBeforeAfterWaiting=(1UL<<6),//即将从休眠中唤醒
kCFRunLoopExit=(1UL<<7),即将退出RunLoop
kCFRunLoopAllActivities=0x0FFFFFFFU//活跃中
}
给RunLoop添加观察者,需要CF类

//如果给runLoop添加观察者,需要CF类    CFRunLoopObserverRef observer=CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {        NSLog(@"---%lu---",activity);    });    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);

RunLoop内部逻辑处理

在这里插入图片描述

转载地址:http://vpwin.baihongyu.com/

你可能感兴趣的文章
谷歌浏览器打不开网址解决办法
查看>>
SQL server内嵌表值函数与多语句表值函数
查看>>
SQL server 存储过程
查看>>
第一个程序hello.c
查看>>
修改dev c++的语言为简体中文与快捷键
查看>>
scanf()接收输入
查看>>
浮点数与四则运算符实例
查看>>
if else分支判断
查看>>
c的if else嵌套与switch分支语句
查看>>
c的循环while,do while
查看>>
c的循环小案例(取随机数)
查看>>
JDBC元数据
查看>>
数据库规范化理论与范式
查看>>
c的for循环
查看>>
JDBC 存储过程(使用java代码编写sql 存储过程)
查看>>
PowerDesigner数据库建模
查看>>
JDBC db层,封装方法(查,增,改,删)
查看>>
c的for循环(二)
查看>>
c的for循环(三)循环控制
查看>>
HTML标签即基本语法
查看>>