-
runtime个人理解
- runtime就是底层的消息发送机制在我们OC中苹果给我们提供了两个关于runtime的API一个是<objc/runtime>另一个是<objc/masge.h>这两个API用来实现底层rumtime运行时的
- runtime主要实在我们运行的时候把我们OC的代码通过objc_msgSend这个函数把OC代码转换成C语言代码
- 在runtime中可以将系统方法进行交换使用也可以获得类中所有属性和属性个数获取类中所有方法包括实例方法和类方法都可以获取到
- 我们可以在mac OX中创建一个Xcode项目然后在终端将自己项目目录通过cd导入终端然后使用ls命令进入文件夹最后使用终端命令clang - rewrite-objc main.m这时候我们会在文件夹看到一个main.pcc的一个文件这个文件就是main.m最底层的代码是使用C++代码进行书写的在这里我们可以初始化一个类看看我们在工程中使用消息发送机制跟main.pcc文件中的发送代码是否一样很幸运代码完全一样的我在这里使用代码进行展示
- // C语言消息发送机制 ====== 一句代码完成runtime初始化操作
- objc_msgSend(objc_msgSend(objc_msgSend(objc_getClass("Person"), @selector(alloc)), @selector(init)), @selector(eat));
- 这句代码就是我们在Xcode中使用runtime书写的最简单的类初始化成实例对象的消息函数 runtime在很多应用场景下都会出现和使用
- 比如我们在归档的时候可以把类中属性获取到归档到一个文件中去然后解档显示出来还有我们可以自定一个NSURL的分类在分类中我们实现自己的请求网络urlwithstring这个方法我们自己将他书写 在这里我们就需要用到runtime我们使用他把两个类方法进行交换从而系统会自动调用我们自己书写的类方法
- 在KVO中我们也会经常见到runtime因为KVO底层就是使用runtime的
- 如果我们需要在Xcode中使用runtime的话我们需要到编译设置区设置一个东西Build Settings这里面我们搜索msg这个东西然后将其设置成NO即可
- 因为在Xcode5.0以后不推荐使用底层代码进行书写代码所以我们需要手动设置个然后我们便可以手动书写自己的runtime代码了
- runloop的个人理解
- runloop底层原理是使用do{}whil{}死循环进行设计的
- 一个线程对应一个runloop 主线程自动开启runloop 子线程需要手动开启runloop
- 如果系统没有runloop的话我们根本进不去main.m因为刚进去直接结束程序了
- UIApplicationMain内部存在一个runloop
- 程序启动之后默认启动一个runloop 主要处理与主线程的相关事件
- runloop只有在外面有操作的时候才会使用如果外部没有操作runloop默认是休眠的状态
- Foundition框架是NSRunloop(OC语言) Core Foundition框架是CFRunLoopRef(C语言)这两个API NSRuLloop是基于CFRunLoopRef书写的
- NSDefultRunLoopModel是默认的runloop模型且每个runloop运行的时候只可以启动一个模型无论他其中有多少模型他都不会运行只会运行
- 你自己设置哪个模型
- NSTackingRunLoopModel这是滚动模型只有在滚动视图的时候才会调用这个模型
- NSRunLoopCommentModel这个模型中包含了NSDefultRunLoopModel和NSTackingRunLoopModel两个模型所以使用和这个模型的时候无论是不是在滚动视图中都会调用runloop线程
- CFRunLoopSourceRef事件源(输入源)
- Source分为两种
- Source0:非基于Port的 用于用户主动触发的事件(点击button 或点击屏幕)
- Source1:基于Port的 通过内核和其他线程相互发送消息(与内核相关)
- 注意:Source1在处理的时候会分发一些操作给Source0去处理
- CFRunLoopObserverRef
- CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变
- RunLoop退出
- 主线程销毁RunLoop退出
- Mode中有一些Timer 、Source、 Observer,这些保证Mode不为空时保证RunLoop没有空转并且是在运行的,当Mode中为空的时候,RunLoop会立刻退出
- 我们在启动RunLoop的时候可以设置什么时候停止
- [NSRunLoop currentRunLoop]runUntilDate:
- [NSRunLoop currentRunLoop]runMode:
- 注意:子线程执行完操作之后就会立即释放,即使我们使用强引用引用子线程使子线程不被释放,也不能给子线程再次添加操作,或者再次开启。
- 注意:创建子线程相关的RunLoop,在子线程中创建即可,并且RunLoop中要至少有一个Timer 或 一个Source 保证RunLoop不会因为空转而退出,因此在创建的时候直接加入,如果没有加入Timer或者Source,或者只加入一个监听者,运行程序会崩溃
- 自动释放池
- Timer和Source也是一些变量,需要占用一部分存储空间,所以要释放掉,如果不释放掉,就会一直积累,占用的内存也就越来越大,这显然不是我们想要的。 那么什么时候释放,怎么释放呢? RunLoop内部有一个自动释放池,当RunLoop开启时,就会自动创建一个自动释放池,当RunLoop在休息之前会释放掉自动释放池的东西,然后重新创建一个新的空的自动释放池,当RunLoop被唤醒重新开始跑圈时,Timer,Source等新的事件就会放到新的自动释放池中,当RunLoop退出的时候也会被释放。
对runtime和runloop的一些个人理解
最新推荐文章于 2020-09-19 15:58:43 发布