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资料非 ...
随机推荐
- [转载]C++中四种强制类型转换方式
C++中四种强制类型转换方式 原文地址:http://www.cnblogs.com/home123/p/6763967.html 类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单( ...
- [TimLinux] 养成一个习惯
1. 习惯 在博客园开博之前,大约六个月之前,我开始给自己定下坚持跑步的目标,从而养成了一个习惯.就在大约半个月前,回顾自己的工作经历的时候,发现还有一个来月自己就工作十年了,为此我树立了一个新的目标 ...
- CoderForces Round60-(1117A,1117B,1117C题解)
A. Best Subsegment time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- redis(7)--redis应用实战
问题1:哨兵模式下客户端应该连接哪个redis-server? 问题2:集群模式下为什么会有MOVED error Redis Java客户端介绍 已有的客户端支持 Redis Java客户端有很多的 ...
- 1.使用大clob入库出错问题
在代码中调用pstm.setString(str) str>4000,这种大字符串插入时出现字符过长插入报错问题. 解决问题:用声明变量方式: <insert id ="inse ...
- 使用docker安装虚拟机并打开ssh连接
一.需求 最近有个需求,要连接很多个linux系统进行测试软件功能,但是我这里只有几个虚拟机,所以需要使用docker来安装几十个或者上百个虚拟机来进行测试. 二.安装docker 这里就不演示怎么安 ...
- 牛客NOIP暑期七天营-提高组3
第一题:破碎的矩阵 题目链接:https://ac.nowcoder.com/acm/contest/932/A 刚看到这题的时候感觉特别熟悉...诶,这不就是codeforces某场比赛的某某 ...
- springboot-eureka交流机制
一 前言 这篇文章参考了官方文档,主要是描述了eureka client 和 eureka server 之间的交流机制: peer to peer 的 对等复制交流机制: eureka 官方文档 二 ...
- shell概述与echo命令
一.Shell概述 1.什么是shell? 由此可见shell是用户与系统进行交互的接口,通过执行各种命令来完成时间处理与调度. 2.shell分类 Shell类别 易学性 可移植性 编辑性 快捷性 ...
- 在WPF中开启摄像头扫描二维码(Media+Zxing)
近两天项目中需要添加一个功能,是根据摄像头来读取二维码信息,然后根据读出来的信息来和数据库中进行对比显示数据. 选择技术Zxing.WPFMediaKit.基本的原理就是让WPFmediaKit来对摄 ...