OC语言之内存管理

来源:互联网 发布:千牛mac登不上去 编辑:程序博客网 时间:2024/05/17 22:28

一、引用计数器

每一个OC对象都有自己的引用计数器,是一个整数(4个字节),表示“对象被引用的次数”,当计数器为0的时候,对象就会被回收,对象回收的依据是对象的计数器是否为0。当对象刚刚产生的时候,计数器默认为1

当使用allocnewcopy创建一个对象时,新对象的引用计数器默认就是1

 

字符串对象不需要release

 

引用计数器的操作:

1.给对象发送一条retain消息,可以使引用计数器值+1retain方法返回对象本身)

2.给对象发送一条release消息,可以使引用计数器值-1

3.可以给对象发送retainCount消息获得当前的引用计数器值

 

当对象引用计数器值为0时,对象就会被销毁,其所占的内存被系统回收;

当一个对象销毁时,系统会自动向对象发送一条dealloc消息;

一般会重写dealloc方法,在对象销毁时做一些操作(类似android中的onDestory);

重写dealloc方法,必须调用[super dealloc],并且放在最后调用。

 

僵尸对象:当对象的引用计数器为0时,此对象为僵尸对象(不可用内存)。

野指针:指向僵尸对象的指针为野指针,野指针再调用会报错,野指针错误

message sent to dealloced instance 0x……

僵尸对象检测开关:点击stop后边->点击“edit scheme->点击“diagnostics->enable zombie objects

int main(){Person *p = [[Person alloc] init];[p release];}


二、多对象内存管理

原则:谁创建(allocnewcopy),谁release(或者autorelease);谁retainrelease

 

按照内存管理原则,set方法代码规范:

@implementation Person- (void)setBook:(Book *)book{//1.判断是不是新传进来的对象if(book != _book){//2.对旧对象做一次release[_book release];//3.对新对象做一次retain_book = [book retain];}}

dealloc方法代码规范:

1.一定要[super dealloc],而且放到最后面

2.对self(当前)所拥有的其他对象做一次release

- (void)dealloc{[_book release];[super dealloc];}

property参数:

1.set方法内存管理相关参数

retainrelease旧值,retain新值(适用于oc对象类型)

assign:直接赋值(默认,适用于非oc对象类型)

copyrelease旧值,copy新值

2.是否要生成setter方法

readwrite:同时生产settergetter的声明、实现(默认)

readonly:只会生成getter的声明、实现

3.多线程管理

nonatomic:性能高(一般就用这个)

atomic:性能低(默认)

4.settergetter方法的名称(一般用在bool类型“@property(getter = isRich) BOOL rich;”)

setter:决定set方法的名称,一定要有个冒号

getter:决定get方法的名称

 

@class的使用:

1.@class的作用:仅仅告诉编译器,某个名称是一个类

@class Person; //仅仅告诉编译器,Person是一个类

2.开发中引用一个类的规范

1>.h文件中用@class类声明类

2>.m文件中用#import来包含类的所有东西

3。两端循环解决方案:

1>一端用retain

2>一端用assin

三、autoreleasesince ios5.0

1.autorelease基本用法

1>autorelease会将对象放到一个自动释放池中

2>当自动释放池呗销毁时,会对池子里的所有对象做一次release操作

3>autorelease方法会返回对象本身

4>调用完autorelease方法后,对象的计数器不变

 

2.autorelease的好处

1>不用再关心对象释放的时间

2>不用再关心什么时候调用release

 

3.autorelease的使用注意

1>占用内存较大的对象不要随便使用autorelease,要使用release对对象进行精确控制

2>占用内存较小的对象没有太大影响

 

@autorealeasepool

{//大括号开始代表创建了释放池

Person *p =[[[Person alloc] init] autorelease];

p.age = 10;

}//大括号结束代表销毁释放池

 

1>自动释放池存放在栈中,先进后出原则;最先创建的池子放在栈的最底部,最上边的池子最先销毁。

2>当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池

 

autorelease错误写法:

1.调用autorelease后又release

2.连续调用两次autorelease(池子销毁时会对对象进行两次release,野指针错误)

 

autorelease前身:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];// 之前的代码会在pool调用release后释放。因为调用autorelease后会将对象放到栈顶的释放池里,此时栈内存只有pool这个释放池,所以是放在了这个pool

Person *p = [[[Person alloc] init] autorelease];

[pool release];

 

快速创建一个已经autorelease过的对象:

在类方法中封装autorelease,创建对象时不要直接用类名,一般用self

+ (id)person{return [[[self alloc] init] autorelease]; // self的好处是,满足子类调用需求,返回的是调用类型的对象}+ (id)personWithAge:(int)age{Person *p = [self person];p.age = age;return p;}int main(){@autoreleasepool{//Person *p = [Person person];Person *p = [Person personWithAge:100];}}

*类方法代码规范,类方法以类名开头。

*系统自带的方法里没有包含allocnewcopy,说明返回的对象都是autorelease

*开发中经常会提供一些类方法,快速创建一个已经autorelease过的对象

 

三、ARC

ARC判断准则:只要没有强指针指向对象,就会释放对象

 

指针分两种:

1>强指针:默认情况下,所有的指针都是强指针 __strong

2>弱指针:__weak

 

当对象没有强指针指向时,会释放对象,同时清空弱指针(防止野指针的情况出现)。

 

ARC特点

1>不允许调用releaseretainretainCount

2>允许重写dealloc,但是不允许调用[super dealloc]

3>@property的参数

*strong:成员变量是强指针,相当于原来的retain(适用于OC对象类型)

*weak:成语变量是弱指针,相当于原来的assign(适用于OC对象类型)

*assign:适用于非OC对象类型

 

ARC转换功能:

ARCARCEdit->Refactor->Convert to Objective-C ARC(或者文件做标记“-f-objc-arc”)

ARC查看:点击项目->Build Settings->搜索“Automatic->Objective-C ARC 标记为yes

ARC转非ARC:点击项目->Build Phases->Complle Sources->双击文件做标记“-fno-objc-arc

 

ARC项目,解决循环引用:

一端用strong

一端用weak

0 0
原创粉丝点击