OC内存管理(非ARC)
来源:互联网 发布:春秋与战国的区别知乎 编辑:程序博客网 时间:2024/06/05 16:26
一、基本原理
1.内存管理的必要性:由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等。如不及时回收内存,可能造成app闪退、崩溃。
2.管理范围:任何继承NSObject的对象,对其他的基本数据类型无效。
本质原因:因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指针也被回收,此时对象已经没有指针指向,但依然存在于内存中,造成内存泄露。
3.引用计数器
用于计算对象被使用的次数,是一个整数(每个对象都有自己的引用计数器:占4个字节)判断对象要不要回收的唯一依据就是计数器是否为0,若不为0则存在。
1>当使用alloc、new或copy创建新对象时,新对象的引用计数器被设置为1.
2>当引用计数器为0时,则此对象所占用内存就会被回收。(发送release消息时,计数器减1)
3>给对象发送retainCount消息获取当前的计数器值
注:retain方法返回的是对象本身(有返回值)
4. 对象的销毁
1>当一个对象的引用计数器为0时,那么它将被销毁,其占用的内存被系统回收。
2>当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般会重写dealloc方法,在这里释放相关的资源,dealloc就像是对象的“临终遗言”。一旦重写了dealloc方法就必须调用[super dealloc],并且放在代码块的最后调用(不能直接调用dealloc方法)。
3>一旦对象被回收了,那么他所占据的存储空间就不再可用,坚持使用会导致程序崩溃(野指针错误)
1.野指针:指向僵尸对象(不可用内存)的指针(虽然对象回收,但是指针的值还在)。
注:给野指针发送消息会报错,报错提示:EXC_BAD_ACCESS
2.僵尸对象:所占内存已经被回收的对象,僵尸对象不能再被使用。(打开僵尸对象检测)
3.空指针:没有指向任何东西的指针(存储的东西是0,null,nil),给空指针发送消息不会报错
注:1)给空指针发送消息不会报错。2) 不能使用[p retaion]让僵尸对象起死复生。
三、内存管理原则
1.原则
只要还有人在使用某个对象,那么这个对象就不会被回收;
只要你想使用这个对象,那么就应该让这个对象的引用计数器+1;
当你不想使用这个对象时,应该让对象的引用计数器-1;
1>谁创建,谁release
a.如果你通过alloc,new,copy来创建了一个对象,那么你就必须调用release或者autorelease方法
b.不是你创建的就不用你去负责
2>谁retain,谁release
只要你调用了retain,无论这个对象时如何生成的,你都要调用release
2.总结
有始有终,有加就应该有减。曾经让某个对象计数器加1,就应该让其在最后-1.
四、内存管理代码规范
1.只要调用了alloc,则必须要有release(或autorelease)
如果对象不是通过alloc产生,则不需要release。
2. Set方法的代码规范
1>基本数据类型:直接复制
- (void)setAge:(int)age{ _age=age;}
2>OC对象类型
- (void)setCar:(Car *)car{ // 先判断是不是新传进来的对象 if(car != _car) { // 对旧对象做一次release [_car release]; //若没有旧对象,则没有影响 // 对新对象做一次retain _car=[car retain]; }}
3.dealloc方法的代码规范
1>一定要[super dealloc],而且要放到最后
2>对self(当前)所拥有的的其他对象做一次release操作
- (void)dealloc{ [_car release]; [super dealloc];}
五、@property参数的内存管理
1.内存管理的相关参数
retain:生成的setter方法中会release旧值,retain新值。(适用于OC对象类型)
assign:直接赋值(默认,适用于非OC对象类型)
copy: release旧值,copy新值
2.是否要生成set方法
readwrite:可读写,同时生成setter和getter的声明和实现(系统默认)
readonly:只读,只会生成getter的声明和实现
3.多线程管理(多个线程同时调用某个方法)
nonatomic:代表方法不要考虑线程安全性问题,告诉系统不在set方法中生成多线程代码。(高性能,禁止多线程,推荐使用)
atomic:代表给方法进行加锁,保证线程安全(默认,低性能)
线程保护机制:防止方法在未写入完成时,被其它线程调用,造成数据错误。
4.setter和getter方法的名称
setter:setter = 方法名,决定了set方法的名称,方法名一定有冒号:
getter:决定了get方法的名称。(一般用在BOOL类型)
修改set和get方法的名称,主要用于布尔类型。因为返回布尔类型的方法名一般以is开头,修改名称一般用在布尔类型中的getter。
@propery(setter=setAbc,getter=isRich) BOOL rich;BOOL b=p.isRich; // 调用
六、循环引用问题以及解决
循环问题引入:每个人有一张身份证,每张身份证对应一个人,不能使用#import的方式相互包含,这就形成了循环引用
1.@class使用方法:
1>作用: @class Card 仅仅告诉编译器,Card只是一个类
使用场合:用于.h声明此类,但是不会引入此类的方法和成员变量。
注意点:仅仅声明这个类,不会将此类的方法和成员变量导入,如果需要,则应该在.m文件中#import此类。
2>引用一个类的规范
a.在.h头文件中用@class来声明类
b.在.m源文件中用#import来包含类的所有东西
3>@class优点
a.解决循环包含的问题。- >只在.m 源文件中进行引用(可以循环声明,A中声明B,B中声明A)
b.提高了性能。->如果被引入类的头文件进行了修改,不需要全部进行重新编译。
4>@class 和 #import 区别
a.#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;(使用类所有信息,包括成员变量和方法)
@class方式只是告诉编译器在A.h文件中 ,声明某个类,不知道此类的所有具体信息。(仅仅声明有这个类)
b.如果有上百个头文件都#import了同一个文件,那么一旦被导入文件的头文件稍有改动,后面引用到这个
文件的所有类的头文件都需要重新拷贝,效率较低。(A->B,B->C,C->D.....一旦A变动,则后面都需要重新编译。程序只编译.h文件)
使用@class方式就不会出现这种问题了,只需在源文件中修改类即可,提高了效率(解决了循环包含问题)
c.在.m实现文件中,如果需要引用到被引用类的成员变量或方法时,还需要使用#import方式引入被引用类。
2.两端循环引用
一端用retain,一端用assign
Card 端 : @property (nonatomic,retain) Person *person;
Person端:@propertor (nonatomic,assign) Card *card
七、Autorelease
1.基本用法
1>会将对象放到一个自动释放池中
2>当自动释放池被销毁时,会对池子里的所有对象做一次release
3>会返回对象本身
4>调用完autorelease方法后,对象的计数器不受影响(销毁时影响)
2.优点
1>不需要再关心对象释放的时间
2>不需要再关心什么时候调用release
3.使用注意
1>占用内存较大的对象,不要随便使用autorelease,应该使用release来精确控制
2>占用内存较小的对象使用autorelease,没有太大的影响
4.错误写法
1>连续调用多次autorelease,释放池销毁时执行两次release(-1吗?)
2>Alloc之后调用了autorelease,之后又调用了release。
5.自动释放池
1>在ios程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的。
2>当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中
6.自动释放池的创建方式
1>ios 5.0以前的创建方式
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
......
[pool release]; // pool drain];用于mac
2>ios5.0以后
@autoreleasepool
{ // 开始代表创建自动释放池
……
} // 结束代表销毁自动释放池
7.Autorelease注意
1>系统自带的方法中,如果不包含alloc new copy等,则这些方法返回的对象都是autorelease的,如[NSDate date];
2>开发中经常会写一些类方法来快速创建一个autorelease对象,创建对象时不要直接使用类名,而是使用self
- OC内存管理(非ARC)
- OC内存管理(ARC)
- 黑马程序员——OC内存管理(非ARC,手工管理)
- 黑马程序员——OC内存管理复习(非ARC部分)
- OC内存管理之ARC
- 内存管理总结-ARC和非ARC
- 黑马程序员---OC基础---内存管理(MRC、ARC)
- OC的ARC(自动内存管理)注意事项
- OC-049.集合中的内存管理(MRC和ARC)
- oc学习之旅:内存管理2修改数组为非ARC版本
- ARC/OC对象自动管理内存
- oc的ARC的内存管理
- OC内存管理--MRC&ARC
- OC内存管理 MRC与ARC
- OC的内存管理方式----MRC & ARC
- OC内存管理-ARC-循环引用
- iOS非ARC内存管理摘要
- iOS非ARC内存管理摘要
- Linux学习笔记(一)——系统中用户切换
- swift面向对象详解
- java设计模式--工厂模式
- 通过Terminal安装VMware Tools
- 找零钱问题
- OC内存管理(非ARC)
- 一道阿里巴巴面试题求解答
- 深入Rails3: ActiveSupport 的 class_attribute
- This is only a manuscript of libsvm experiment
- cordova跳转到js界面黑屏
- MyEclipse 2015中添加Tomcat服务器
- 最优装载
- Linux学习笔记(二)——ubuntu下如何切换到root登陆
- 关于quartz的并发问题