黑马程序员_OC基础11_内存管理01

时间:2022-11-20 16:17:11

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

一、概念

1、对任何继承了NSObject的对象进行内存释放管理

2、基础数据类型不包括在内


二、作用

1、由于移动设备内存十分有限,所以要对app使用的内存空间进行控制,比如回收一些不需要使用的对象、变量等


三、使用方法

1、引用计数器

1>概念

每个OC对象都有一个引用计数器,表示对象被引用的次数,占4个字节内存空间

2>作用

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

当一个对象的引用计数器值为0时,对象占用的内存就会被系统回收。

我们需要做的就是在对象不再需要使用的时候及时使其计数器变为零

3>使用方法

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

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

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


2、对象销毁

1>当对象的引用计数器为零时,它将被销毁,内存被系统回收

2>对象销毁时系统会向对象发送dealloc消息,一般我们重写消息,使其释放相关资源

3>重写dealloc方法时,一定要将父类的dealloc方法写在最后

4>不要直接调用dealloc方法

5>对象被销毁后如果继续使用,将引发“野指针”错误


3、注意点(原则)

1>一个对象还有人在使用,这个对象就不能释放

如果你要使用某个对象,就使其计数器+1(retain),如果你不再使用某个对象就使其计数器-1(release)

2>谁创建,谁release

如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease

假设我有一个person类,并且在person类里有一个book类的成员变量

int main()
{
Person *p = [[Person alloc] init];
Book *b = [[Book alloc] init];
p.book = b;

[b release]; // 使用了alloc,所以要release
[p release]; // 使用了alloc,所以要release

return 0;
}

Person的set方法
- (void)setBook:(Book *)book

{
if (book !=_book) // 判断一下是不是原来那本书

{
[_book release]; // 新书换旧书,旧书release
_book = [book retain]; // 新书retain
}
}

 Person的dealloc方法

- (void)dealloc
{
[_book release]; // 当Person对象被回收时,将其占有的书进行release操作
[super dealloc]; // 调用父类方法释放父类对象
}


4、@property参数

1>内存管理相关

retain:release旧值,retain新值(OC对象)

assign:直接赋值,无内存管理(非OC对象) —  默认

copy:release旧值,copy新值(OC对象,一般用于NSString *)



2>是否自动生成set方法

readwrite:同时生成set方法和get方法  —  默认

readonly:只生成get方法



3>多线程管理
atomic:性能低  —  默认
nonatomic:性能高



4>控制setter和getter名称(无默认参数,冒号不要忘记,不常用)

setter:设置set方法名称

getter:设置getter方法名称


四、循环引用

1、概念

当两个类互相引用并在.h文件中都#import对方时,编译器会报错

2、解决方法

这时,我们在.h文件中使用@class引用类

.h文件中编译器只需要知道这是一个类,具体里面的参数在.m文件中引用即可

3、循环retain

1>概念

同样,在内存管理时,Person在其类中将所拥有的book进行了retain操作

同时,Book在其类中也将其拥有者进行了retain操作

这样就会引发循环retain,谁都无法释放

2>解决方法

当两个对象要互相引用时,一端使用retain,一端使用assign



五、autorelease

1、概念

1>给某个对象发送一条autorelease消息时,就会将这个对象加到一个自动释放池中

2>当自动释放池销毁时,会给池子里面的所有对象发送一条release消息

3>调用autorelease方法时并不会改变对象的计数器,并且会返回对象本身

4>autorelease pool以栈的形式存储在内存中,对象发送autorelease消息后,这个对象会被添加到栈顶释放池

2、使用方法

以iOS 5.0为界

5.0后使用

@autorelease
{
// 代码
}

5.0前使用

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// 代码


3、注意点

1>使用autorelease的对象不用再手动release一遍

// 以前
Book *book = [[Book alloc] init];
[book release];

// autorelease
@autorelease
{
Book *book = [[[Book alloc] init] autorelease];
}

2>一般情况下,除alloc,new,copy操作创建出来的对象外,其余已经做过autorelease操作

@autorelease
{
NSNumber *n = [NSNumber numberWithInt:100];
NSString *s = [NSString stringWithFormat:@"jack"];
NSString *s2 = @"rose";
}


---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com