RunLoop 和 autoreleasepool
RunLoop 和 autoreleasepool
- RunLoop和线程的一一对应的,对应的方式是以key-value的方式保存在一个全局字典中
- 主线程的RunLoop会在初始化全局字典时创建
- 子线程的RunLoop会在第一次获取的时候创建,如果不获取的话就一直不会被创建
- RunLoop会在线程销毁时销毁
在iOS应用启动后会注册两个Observer管理和维护AutoreleasePool。不妨在应用程序刚刚启动时打印currentRunLoop可以看到系统默认注册了很多个Observer,其中有两个Observer的callout都是** _ wrapRunLoopWithAutoreleasePoolHandler**,这两个是和自动释放池相关的两个监听。
第一个Observer会监听RunLoop的进入,它会回调objc_autoreleasePoolPush()向当前的AutoreleasePoolPage增加一个哨兵对象标志创建自动释放池。这个Observer的order是-2147483647优先级最高,确保发生在所有回调操作之前。
第二个Observer会监听RunLoop的进入休眠和即将退出RunLoop两种状态,在即将进入休眠时会调用objc_autoreleasePoolPop() 和 objc_autoreleasePoolPush() 根据情况从最新加入的对象一直往前清理直到遇到哨兵对象。而在即将退出RunLoop时会调用objc_autoreleasePoolPop() 释放自动自动释放池内对象。这个Observer的order是2147483647,优先级最低,确保发生在所有回调操作之后。
主线程的其他操作通常均在这个AutoreleasePool之内(main函数中),以尽可能减少内存维护操作(当然你如果需要显式释放【例如循环】时可以自己创建AutoreleasePool否则一般不需要自己创建)。
其实在应用程序启动后系统还注册了其他Observer(例如即将进入休眠时执行注册回调_UIGestureRecognizerUpdateObserver用于手势处理、回调为_ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv的Observer用于界面实时绘制更新)和多个Source1(例如context为CFMachPort的Source1用于接收硬件事件响应进而分发到应用程序一直到UIEvent)。
在主线程执行的代码,通常是写在诸如事件回调、Timer回调内的。这些回调会被 RunLoop 创建好的 AutoreleasePool 环绕着,所以不会出现内存泄漏,开发者也不必显示创建 Pool 了。
自动释放池的创建和释放,销毁的时机如下所示
- kCFRunLoopEntry; // 进入runloop之前,创建一个自动释放池
- kCFRunLoopBeforeWaiting; // 休眠之前,销毁自动释放池,创建一个新的自动释放池
- kCFRunLoopExit; // 退出runloop之前,销毁自动释放池
什么情况下需要创建自动释放池?
其实自动释放池存在的意义是为了延迟释放一些对象,延迟向对象发送release消息。在实际的开发中,有两种情况是需要手动创建自动释放池的。
1、在多线程中,因为子线程中可能会使用便利构造器等方法来创建对象(类方法),那么这些对象的释放只能放在自动释放池中,此时需要在子线程中添加自动释放池。
使用便利构造器等方法来创建对象是autorelease的对象,需要制动释放池才能释放
主线程已经添加过自动释放池,在main函数里面。
2、就是如果一段代码里面(比如for循环)大量使用便利构造器创建对象,也需要手动添加自动释放池。
什么是便利构造器?
便利构造器在初始化方法的基础上前进了一⼩小步。封装了对象创建过程。
便利构造器是“+”方法,返回本类型的实例,方法名以类名开头,其实一些类中的静态方法也是便利构造器。
可以有0到多个参数。内部实现:封装了alloc和初始化方法。使用起来更加简洁。
默认主线的运行循环(runloop)是开启的,子线程的运行循环(runloop)默认是不开启的,也就意味着子线程中不会创建autoreleasepool,所以需要我们自己在子线程中创建一个自动释放池。(子线程里面使用的类方法都是autorelease,就会没有池子可释放,也就意味着后面没有办法进行释放,造成内存泄漏。)----在主线程中如果产生事件那么runloop才回去创建autoreleasepool,通过这个道理我们就知道为什么子线程中不会创建自动释放池了,因为子线程的runloop默认是关闭的,所以他不会自动创建autoreleasepool,需要我们手动添加
NSThread和NSOperationQueue开辟子线程需要手动创建autoreleasepool,GCD开辟子线程不需要手动创建autoreleasepool,因为GCD的每个队列都会自行创建autoreleasepool
RunLoop 和 autoreleasepool的更多相关文章
- Runloop与autoreleasePool联系
autoreleasePool自动释放池,ARC模式下,苹果会自动进行内存管理,不需要我们手动去管理内存.这对于苹果开发者来说,省去了很多事情,不用再每天为了内存管理浪费掉宝贵的开发时间.大家都知道, ...
- 都在说RunLoop...... 到底什么是RunLoop?
RunLoop(消息循环):说白了就是一种事件监听循环.就好比是一个while循环,监听到事件就起来,没有就休息. 介绍: 它可以在不同模式下进行切换,iOS有五种模式,其中UIInitializat ...
- iOS Runloop 消息循环
介绍 Runloop是一种事件监听循环,可以理解成一个while死循环,监听到事件就起来,没有就休息. Runloop可以在不同模式下进行切换,iOS有五种模式,其中UIInitializationR ...
- iOS开发——高级篇——Runloop相关一
一.什么是runLoop 1.说白了,runloop就是运行循环 2.runloop,他是多线程的法宝 通常来讲,一个线程一次只能执行一个任务,执行完之后就退出线程.但是,对于主线程是不能退出的,因此 ...
- runloop 小记
一.什么是runLoop 1.说白了,runloop就是运行循环 2.runloop,他是多线程的法宝 通常来讲,一个线程一次只能执行一个任务,执行完之后就退出线程.但是,对于主线程是不能退出的,因此 ...
- iOS面试题 -总结 ,你的基础扎实吗?
1.#import和#include的区别,@class代表什么? (1)#import指令是Object-C针对#include的改进版本,#import确保引用的文件只会被引用一次,这样你就不会陷 ...
- iOS 面试题搜集
1.#import和#include的区别,@class代表什么? 2.浅拷贝和深拷贝区别是什么? 3.Objective-C中类别和类扩展的区别? 4.Objective-C堆和栈的区别? 5.内存 ...
- BAT面试的准备—iOS篇
本文主要用于记录在准备BAT面试中关于iOS遇到的问题和做一些相关面试题的笔记 iOS网络层设计 1.网络层和业务层的对接设计 使用哪种交互模式来和业务层对接 : 使用Delegate为主,目的是为了 ...
- RunLoop 总结:RunLoop的应用场景(一)
参考资料 好的书籍都是值得反复看的,那好的文章,好的资料也值得我们反复看.我们在不同的阶段来相同的文章或资料或书籍都能有不同的收获,那它就是好文章,好书籍,好资料.关于iOS 中的RunLoop资料非 ...
随机推荐
- luogu P1412 经营与开发 |dp
题目描述 4X概念体系,是指在PC战略游戏中一种相当普及和成熟的系统概念,得名自4个同样以"EX"为开头的英语单词. eXplore(探索) eXpand(拓张与发展) eXplo ...
- Chrome DevTools开发者工具调试
1-1 Chrome DevTools 功能简介 (九大功能面板) (1)Elements元素面板 检查和调整页面,调试DOM,调试CSS (2)Network网络面板 调试请求,了解页面静态资源分布 ...
- 洛谷 P2254 [NOI2005]瑰丽华尔兹(单调栈优化DP)
题目描述 不妨认为舞厅是一个N行M列的矩阵,矩阵中的某些方格上堆放了一些家具,其他的则是空地.钢琴可以在空地上滑动,但不能撞上家具或滑出舞厅,否则会损坏钢琴和家具,引来难缠的船长.每个时刻,钢琴都会随 ...
- 记录一些实用的小技巧-JS篇
1.16进制随机颜色 let color = '#'+Math.random().toString(16).slice(-6) 2.类型判断工具函数 function isType(target, t ...
- Postman 关联接口测试(带有token鉴权)
Postman 关联接口测试(带有token鉴权) 一.登陆接口 创建一个request请求 在Tests中添加JavaScript代码,用来获取鉴权 pm.test("V2", ...
- 【MyBatis】配置文件提示
[MyBatis]配置文件提示 官方帮助文档:http://www.mybatis.org/mybatis-3/zh/index.html config配置 http://mybatis.org/dt ...
- linux之文件的属性
1.我们使用ls -al查看目录下的文件 2.先看第一个权限 -rw-r--r-- 1 hui hui 3806 Oct 3 17:48 .bashrc 对于.bashrc,其权限是-rw-r--r- ...
- Linux服务器部署.Net Core笔记:一、开启ssh服务
开启ssh服务需要root权限,先用root账户登陆系统 在安装ssh前我们先更新一下yum:yum update 先检查有没有安装ssh服务:rpm -qa | grep ssh 如果没有安装ssh ...
- vue 中 px转vw的用法
下面介绍最简单的用法 1 下载依赖 npm install postcss-import postcss-loader postcss-px-to-viewport --save-dev 2 在项目根 ...
- CSS入门(背景各种属性的详解、垂直居中和过渡效果的详解、渐变效果的简单讲解、雪碧图和精灵图)
一.各种背景属性 1.background-image 属性为元素设置背景图像. 元素的背景占据了元素的全部尺寸,包括内边距和边框,但不包括外边距. 默认地,背景图像位于元素的左上角,并在水平和垂直方 ...