一、基本原理

1.什么是内存管理

  • 内存管理的重要性:
  • 移动设备的内存极其有限,每个app所能占用的内存是有限制的
  • 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间。比如回收一些不需要使用的对象、变量等
  • 管理范围:任何继承了NSObject的对象,对其他基本数据类型(int、char、float、double、struct、enum等)无效

2.什么是引用计数器

  • 每个OC对象都有自己的引用计数器,是一个整数,表示“对象被引用的次数”,即有多少人正在使用这个OC对象
  • 每个OC对象内部专门有4个字节的存储空间来存储引用计数器

3.引用计数器的作用 MRC (MannulReference Counting)

  • 当使用alloc、new或者copy创建一个新对象时,新对象的引用计数器默认就是1
  • 当一个对象的引用计数器值为0时,对象占用的内存就会被系统回收。换句话说,如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收,除非整个程序已经退出

4.引用计数器的操作

  • 给对象发送一条retain消息,可以使引用计数器值+1(retain方法返回对象本身)
  • 给对象发送一条release消息,可以使引用计数器值-1 (release并不代表对象的销毁、回收对象,仅仅是计数器-1)
  • 可以给对象发送retainCount消息获得当前的引用计数器值

5.对象的销毁(dealloc)

  • 当一个对象的引用计数器值为0时,那么它将被销毁,其占用的内存被系统回收
  • 当一个对象被销毁时,系统会自动向对象发送一条dealloc消息
  • 一般会重写dealloc方法,在这里释放相关资源,dealloc就像对象的遗言
  • 一旦重写了dealloc方法,就必须调用[super dealloc],并且放在最后面调用
  • 不要直接调用dealloc方法
  • 一旦对象被回收了,它占用的内存就不再可用,坚持使用会导致程序崩溃(野指针错误)

6.野指针、空指针

二、Xcode的设置

1.取消ARC

要想手动调用retain、release等方法,在创建项目的时候不要勾选ARC

2.开启僵尸对象监控

默认情况下,Xcode是不会管僵尸对象的,使用一块被释放的内存也不会报错。为了方便调试,应该开启僵尸对象监控

三、内存管理原则

1.原则分析

  • QQ堂开房间原理:只要房间还有人在用,就不会解散
  • 只要还有人在用某个对象,那么这个对象就不会被回收
  • 只要你想用这个对象,就让对象的计数器+1
  • 当你不再使用这个对象时,就让对象的计数器-1

2.谁创建,谁release

  • 如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease
  • 换句话说,不是你创建的,就不用你去[auto]release

3.谁retain,谁release

  • 只要你调用了retain,无论这个对象是如何生成的,你都要调用release

4.总结

  • 有始有终,有加就有减
  • 曾经让对象的计数器+1,就必须在最后让对象计数器-1

四、set方法的内存管理

如果你有个OC对象类型的成员变量,就必须管理这个成员变量的内存。比如有个Book *_book

1.set方法的实现

- (void)setBook:(Book *)book{

if (book != _book) {

[_book release];

_book = [book retain];

}

}

2.dealloc方法的实现

- (void)dealloc {

[_book release];

[super dealloc];

}

五、@property参数

1.控制set方法的内存管理

  • retain : release旧值,retain新值(用于OC对象)
  • assign : 直接赋值,不做任何内存管理(默认,用于非OC对象类型)
  • copy   : release旧值,copy新值(一般用于NSString *)

2.控制需不需生成set方法

  • readwrite :同时生成set方法和get方法(默认)
  • readonly  :只会生成get方法

3.多线程管理

  • atomic    :性能低(默认)
  • nonatomic :性能高

4.控制set方法和get方法的名称

  • setter : 设置set方法的名称,一定有个冒号:
  • getter : 设置get方法的名称

六、循环引用

1.@class

  • 使用场景

   对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类

   这种代码编译会报错。当使用@class在两个类相互声明,就不会出现编译报错

  • 用法概括

   使用 @class 类名; 就可以引用一个类,说明一下它是一个类

  • 和#import的区别

   #import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在A.h文件中 B *b 只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息

   如果有上百个头文件都#import了同一个文件,或者这些文件依次被#improt,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率 也是可想而知的,而相对来 讲,使用@class方式就不会出现这种问题了

   在.m实现文件中,如果需要引用到被引用类的实体变量或者方法时,还需要使用#import方式引入被引用类

2.循环retain

  • 比如A对象retain了B对象,B对象retain了A对象
  • 这样会导致A对象和B对象永远无法释放

3.解决方案

  • 当两端互相引用时,应该一端用retain、一端用assign

七、autorelease

1.autorelease

  • 给某个对象发送一条autorelease消息时,就会将这个对象加到一个自动释放池中
  • 当自动释放池销毁时,会给池子里面的所有对象发送一条release消息
  • 调用autorelease方法时并不会改变对象的计数器,并且会返回对象本身
  • autorelease实际上只是把对release的调用延迟了,对于每一次autorelease,系统只是把该对象放入了当前的autorelease pool中,当该pool被释放时,该pool中的所有对象会被调用Release

2.自动释放池的创建

  • ios 5.0后

@autoreleasepool

{

// ....

}

  • ios 5.0前

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// .....

[pool release]; // 或[pool drain];

  • 在程序运行过程中,可以创建多个自动释放池,它们是以栈的形式存在内存中
  • OC对象只需要发送一条autorelease消息,就会把这个对象添加到最近的自动释放池中(栈顶的释放池)

3.应用实例

  • 跟release的对比

  以前:

   Book *book = [[Book alloc] init];

   [book release];

  现在:

   Book *book = [[[Book alloc] init] autorelease];

   // 不要再调用[book release];

  • 一般可以为类添加一个快速创建对象的类方法

  + (id)book {

  return [[[Book alloc] init] autorelease];

  }

  外界调用[Book book]时,根本不用考虑在什么时候释放返回的Book对象

4.规律

  • 一般来说,除了alloc、new或copy之外的方法创建的对象都被声明了autorelease
  • 比如下面的对象都已经是autorelease的,不需要再release

  NSNumber *n = [NSNumber numberWithInt:100];

  NSString *s = [NSString stringWithFormat:@"jack"];

  NSString *s2 = @"rose";

转载于:https://www.cnblogs.com/oc-bowen/p/5053039.html

OC 内存管理之手动内存管理MRC相关推荐

  1. iOS开发——MRC(手动内存管理)

    iOS开发--MRC(手动内存管理) 内存分配区域 栈区 堆区 总结 常量区 总结 代码区 总结 全局区 关于如何查看一个对象在堆区 / 栈区 需要知道的知识 手动引用计数MRC 四个法则 非自己生成 ...

  2. 【iOS开发】——MRC(手动内存管理)的一些补充

    [iOS开发]--MRC(手动内存管理)的一些补充 前言 野指针与空指针 多个对象内存管理的思想 玩家没有使用过房间 一个玩家使用一个游戏房间的情况 一个玩家使用一个房间 r 后,换到另一个房间 r2 ...

  3. Go 语言中手动内存管理

    2019独角兽企业重金招聘Python工程师标准>>> Go 语言是自带GC的, 相对C语言等的手动内存管理省事很多, 弊端便是会消耗更多的内存, 以及在GC时导致整个程序的停顿. ...

  4. Oracle 内存一 手动内存管理,自动内存管理

    oracle的内存分为两个部分.一个是SGA(system global area),一个是PGA(program global area).所谓的内存管理,就是对这两部分区域进行管理.oracle的 ...

  5. 使用jemalloc在Go中进行手动内存管理

    目录 通过Cgo创建内存 jemalloc 在字节片上放置Go结构 用分配器摊销Calloc的成本 明智地参考 处理分配的GB 排序可变长度数据 捕捉内存泄漏 结论 推荐阅读 曼尼斯·赖·贾 因(Ma ...

  6. go 1.20 手动内存管理arena

    go1.20新特性,手动内存管理 测试特性安装go1.20rc go install golang.org/dl/go1.20rc1@latest go1.20rc1 download 使用go1.2 ...

  7. 视频教程-iOS底层原理班(下)/OC对象/关联对象/多线程/内存管理/性能优化-iOS

    iOS底层原理班(下)/OC对象/关联对象/多线程/内存管理/性能优化 小码哥教育CEO,曾开发了2个iOS的流行开源框架(MJRefresh.MJExtension),目前在国内的使用率非常高. 李 ...

  8. Oracle 内存一 手动内存管理,自动内存管理

    oracle的内存分为两个部分.一个是SGA(system global area),一个是PGA(program global area).所谓的内存管理,就是对这两部分区域进行管理.oracle的 ...

  9. iOS底层原理班(下)/OC对象/关联对象/多线程/内存管理/性能优化-李明杰-专题视频课程...

    iOS底层原理班(下)/OC对象/关联对象/多线程/内存管理/性能优化-236人已学习 课程介绍         得遇名师,突飞猛进!iOS培训王者MJ(李明杰)老师精心研发,iOS进阶课程,实用技术 ...

  10. 属性与内存管理(属性与内存管理都是相互关联的)

    <span style="font-size:18px;"> 属性与内存管理(属性与内存管理都是相互关联的)第一部分一,属性:属性是OC2.0之后出来的新语法,用来取代 ...

最新文章

  1. codeforces1700数学:E2. Close Tuples (hard version)[组合计数 逆向统计] D. Circle Game[对称博弈考虑对称状态的胜负]
  2. rocketmq怎么保证消息一致性_RocketMQ为什么要保证订阅关系的一致性?
  3. 算法-----买卖股票的最佳时机(Java 版本)
  4. 成功解决Git Bash运行脚本命令下载文件到默认C盘路径的问题
  5. 210317阶段三opencv
  6. linux opendir php,php opendir()列出目录下所有文件的实例代码
  7. php 微信分享功能_使用php怎么实现一个微信分享朋友链接功能
  8. Self Introduction
  9. 中国高校改名(总结篇)(转载)
  10. 导出数据库设计文档的几种方案
  11. JAVA HD japan_电竞小金刚:优派VX2778-hd-PRO
  12. 使用JDBC创建出版社和书籍管理系统
  13. sympy的dsolve函数
  14. 并行编程--MPI开发入门
  15. LTE的CQI及下行码率计算
  16. 利用H5SVG实现线性动画效果
  17. 黄一老师:管理者需要知道的“三多”和“三少”
  18. 团体标准的意义,办理团体标准的好处
  19. 腾讯云:轻量服务器8核16G18M配置性能及限制条件说明
  20. unix操作系统可以用于服务器管理吗,UNIX操作系统使用必备(四)

热门文章

  1. Floyd算法 求多源汇最短路
  2. python中的计时器timeit_python中的计时器:timeit
  3. 软件测试 vb,使用VB6.0进行自动化测试
  4. java获取hive表结构_oracle12c中 表结构转换成hive表结构的脚本
  5. 自学c语言每天一小时,昨天学习C语言第五天, 自学失败的一天
  6. Confluence 6 重新获得附件指南
  7. 十二周二次课 12.6 Nginx安装 12.7 默认虚拟主机 12.8 Nginx用户认证 12.
  8. c#简要概括面向对象的三大特征(三)
  9. 谁先看到苏神咬人? 世界杯直播背后的云
  10. 配置Eclipse远程调试weblogic应用的环境