OC内存管理
2016-12-18 21:13
246 查看
OC内存管理
1.内存管理的重要性
移动设备的内存极其有限,每个app所能占用的内存是有限制的下列行为都会增加一个app的内存占用
创建一个OC对象
定义一个变量
调用一个函数或者方法
当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间。比如回收一些不需要使用的对象、变量等
如果app占用内存过大, 系统可能会强制关闭app, 造成闪退现象, 影响用户体验
2.什么是内存管理
如何回收那些不需要再使用的对象?那就得学会OC的内存管理
所谓内存管理, 就是对内存进行管理, 涉及的操作有:
分配内存 : 比如创建一个对象, 会增加内存占用
清除内存 : 比如销毁一个对象, 能减小内存占用
内存管理的管理范围
任何继承了NSObject的对象
对其他非对象类型无效(int、char、float、double、struct、enum等 )
只有OC对象才需要进行内存管理的本质原因:
OC对象存放于堆里面
非OC对象一般放在栈里面(栈内存会被系统自动回收)
3.堆和栈
栈(操作系统):由操作系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈(先进后出);堆(操作系统):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表。
int main(int argc, const char * argv[]) { @autoreleasepool { int a = 10; // 栈 int b = 20; // 栈 // p : 栈 // Person对象(计数器==1) : 堆 Person *p = [[Person alloc] init]; } // 经过上一行代码后, 栈里面的变量a\b\p都会被回收 // 但是堆里面的Person对象还会留在内存中,因为它的引用计数器还是1 return 0; }
引用计数器
1.什么是引用计数器
系统是如何判断什么时候需要回收一个对象所占用的内存?根据对象的引用计数器,引用计数器为0时内存被回收
什么是引用计数器:
每个OC对象都有自己的引用计数器
它是一个整数
从字面上, 可以理解为”对象被引用的次数”
也可以理解为: 它表示有多少人正在用这个对象
2.引用计数器的作用
简单来说, 可以理解为:引用计数器表示有多少人正在使用这个对象
当没有任何人使用这个对象时, 系统才会回收这个对象, 也就是说
当对象的引用计数器为0时,对象占用的内存就会被系统回收
如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收(除非整个程序已经退出 )
任何一个对象, 刚生下来的时候, 引用计数器都为1
当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1
3.引用计数器的操作
要想管理对象占用的内存, 就得学会操作对象的引用计数器引用计数器的常见操作
给对象发送一条retain消息,可以使引用计数器值+1(retain方法返回对象本身)
给对象发送一条release消息, 可以使引用计数器值-1
给对象发送retainCount消息, 可以获得当前的引用计数器值
需要注意的是: release并不代表销毁\回收对象, 仅仅是计数器-1
dealloc方法
1.dealloc方法基本概念
当一个对象的引用计数器值为0时, 这个对象即将被销毁,其占用的内存被系统回收对象即将被销毁时系统会自动给对象发送一条dealloc消息 (因此, 从dealloc方法有没有被调用, 就可以判断出对象是否被销毁)
dealloc方法的重写
一般会重写dealloc方法, 在这里释放相关资源, dealloc就是对象的遗言
一旦重写了dealloc方法, 就必须调用[super dealloc], 并且放在最后面调用(MRC)
使用注意
不能直接调用dealloc方法
一旦对象被回收了, 它占用的内存就不再可用, 坚持使用会导致程序崩溃(野指针错误)
野指针和空指针
1.僵尸对象
已经被销毁的对象(不能再使用的对象)2.野指针
指向僵尸对象(不可用内存)的指针给野指针发消息会报EXC_BAD_ACCESS错误
控制台打印:message sent to deallocated instance 0x7f84085cfc50
3.空指针
没有指向存储空间的指针(里面存的是nil, 也就是0),给空指针发消息是没有任何反应的为了避免野指针错误的常见办法,在对象被销毁之后, 将指向对象的指针变为空指针
内存管理原则
1.内存管理原则
苹果官方规定的内存管理原则谁创建谁release :
如果你通过alloc、new、copy或mutableCopy来创建一个对象,那么你必须调用release或autorelease
谁retain谁release:
只要你调用了retain,就必须调用一次release
总结就是
有加就有减:让对象的计数器+1,就必须在最后让对象计数器-1
2.多对象内存管理
只要还有人在用某个对象,那么这个对象就不会被回收只要你想用这个对象,就让对象的计数器+1
当你不再使用这个对象时,就让对象的计数器-1
3.setter方法内存管理
(1)release之前的对象(2)retain需要使用的对象
(3)只有传入的对象和之前的对象不同才需要release和retain
- (void)setRoom:(Room *)room { // 避免过度释放 if (room != _room) { // 对当前正在使用的房间(旧房间)做一次release [_room release]; // 对新房间做一次retain操作 _room = [room retain]; } }
4.dealloc方法的内存管理
- (void)dealloc { // 当人不在了,代表不用房间了 // 对房间做一次release操作 [_room release]; [super dealloc]; }
@property参数
1.控制set方法的内存管理retain : release旧值,retain新值(用于OC对象)
assign : 直接赋值,不做任何内存管理(默认,用于非OC对象类型)
copy : release旧值,copy新值(一般用于NSString、Block)
2.控制需不需要生成set方法
readwrite :同时生成set方法和get方法(默认)
readonly :只会生成get方法
3.多线程管理
atomic :性能低(默认)
nonatomic :性能高
4.控制set方法和get方法的名称
setter : 设置set方法的名称,一定有个冒号:
getter : 设置get方法的名称
注意: 不同类型的参数可以组合在一起使用
@class
1.@class基本概念
作用可以简单地引用一个类
简单使用
@class Dog;
仅仅是告诉编译器:Dog是一个类; 并不会包含Dog这个类的所有内容
具体使用:
在.h文件中使用@class引用一个类
在.m文件中使用#import包含这个类的.h文件
2.@class其它应用场景
对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类这种嵌套包含的代码编译会报错
#import "B.h" @interface A : NSObject { B *_b; } @end #import “A.h" @interface B : NSObject { A *_a; } @end // 当使用@class在两个类相互声明,就不会出现编译报错 @class B; @interface A : NSObject { B *_b; } @end @class A; @interface B : NSObject { A *_a; } @end
3.@class和#import
作用上的区别:import会包含引用类的所有信息(内容), 包括引用类的变量和方法
@class仅仅是告诉编译器有这么一个类, 具体这个类里有什么信息, 完全不知
效率上的区别:
如果有上百个头文件都#import了同一个文件,或者这些文件依次被#import, 那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍 , 编译效率非常低
相对来讲,使用@class方式就不会出现这种问题了
循环retain
1.循环retian基本概念循环retain的场景:
比如A对象retain了B对象,B对象retain了A对象
循环retain的弊端:
这样会导致A对象和B对象永远无法释放
循环retain的解决方案:
当两端互相引用时
MRC: 应该一端用retain、一端用assign
ARC: 应该一端用strong,一端用weak
相关文章推荐
- IntelliJ IDEA系列编辑器安装GO插件
- 依赖注入
- 关于QT编程使用组件的大大的提醒SSS
- jsp路径总结
- Vector Tile
- JSON Web Token单点登录设计
- maven的pom.xml的讲解
- 如何发表高质量SCI论文
- 枚举和file类的知识点
- 树梅派应用17:树莓派3如何使用蓝牙
- 1024. Palindromic Number (25)
- leetcode 434. Number of Segments in a String
- //1.调整数组使奇数全部都位于偶数前面。 //题目: //输入一个整数数组,实现一个函数,来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。
- 20145231 《信息安全系统设计基础》第14周学习总结
- POJ-1028 Web Navigation 和TOJ 1196. Web Navigation
- CSS浮动(float)属性的原理以及清除浮动的几种方法
- Halcon_Hough变换检测直线,检测圆
- 新浪微博接口清单
- 新浪微博接口清单
- 新浪微博接口清单