1-内存管理
1>内存管理
内存管理对于开发iOS来说,很重要,是精髓。学会了内存管理在开发的时候就可以精确分配存储空间。
管理范围:任何继承了NSObject的对象,都需要管理。基本数据类型不需要(int char double float struct enum)
2>引用计数器
每个OC对象都有自己的引用计数器,表示对象被引用的次数
一个新对象,默认计数器就是1,成为0则被销毁。系统会自动向对象发送一条dealloc消息。
给对象发送一条retain消息,对象计数器+1;
给对象发送一条release消息,对象计数器-1;
给对象发送一条retainCount,获取当前计数器情况。
一句话:谁retain,谁release。谁alloc,new,谁release(outorelease).
在对象被销毁时,就会调用dealloc方法。
我们可以重写dealloc方法,达到一些需要:
<span style="font-size:18px;">- (void)dealloc
{
NSLog(@"对象被回收");
[super dealloc];
}
</span>
僵尸对象:所占内存已经被回收的对象。
野指针:指向僵尸对象(不可用内存)的指针。为了防止野指针错误,p = nil;而[p release],是给空指针发消息。
空指针:没有任何东西的指针(存储的东西是nil,NULL,0),给空指针发送release消息不回报错。
3.内存管理相关的参数
1>retain: release旧值,retain新值。
2>assign:(set方法)直接赋值(默认),@property(assign) int age(适用于非oc对象类型)
3>copy:release旧值,copy新值。
4.set方法内存管理
基本数据类型不需要管理内存
<span style="font-size:18px;">- (void)setAge:(int)age
{
_age = age;
}
</span>
如果更换某个对象,使用新对象,应该在更换对象前对旧对象进行一次release.
<span style="font-size:18px;">- (void)setCar:(Car *)car
{
if(car != _car)// 先判断是不是新传进来的对象
{
[_car release];// 对旧对象进行一次销毁
}
_age = [age retain];// 对新对象retain
}</span>
dealloc方法的代码规范
1>一定要[super dealloc],而且放到最后。
2>对(self)当前所拥有的其他对象做一次release
- (void)dealloc
{// 当人不在了,对车坐一次release操作
[_car release];
NSLog(@"%d岁的person被回收了", _age);
[super dealloc];
}
4.property。
1.简单写法(针对对象类型):
会自动生成book的set方法。会release旧值,retain新值。
<span style="font-size:18px;">@property (retain) Book *book;
</span>
相当于
- (void)setBook:(Book *)book
{
if(_book != book)
{
[_book release];
_book = [book retain];
}
}
2.readonly参数和readwrite参数,它们属于同一类型只可以写一个。
//只生成getter的声明和实现
<span style="font-size:18px;">@property (readonly) int height;
</span>
//同时生成setter和getter的声明和实现
<span style="font-size:18px;">@property(readwrite);</span>
3.多线程管理
@nonatomic:性能高,一般使用这个。
@atomic:默认情况下,性能低。
4.setter和getter方法的名称
setter:决定了setter的名称,后面一定要有个冒号:
getter:决定了getter的名称。一般用在bool类型.
<span style="font-size:18px;">@property (getter = abc,setter = setAbc:) age;
</span>
这种方式一般在bool中使用。
例如:
//返回bool类型的方法名一般以is开头
<span style="font-size:18px;">@property (getter = isRich) BOOL rich;
</span>
在外面就可以这样调用:
<span style="font-size:18px;">Person *p = [[Person alloc] init];
p.rich = YES;
BOOL b = p.isRich;</span>
5.@class仅告诉编译器,它所代表的是一个类。
开发中使用:在.h文件中用@class来声明类,在.m中用#import来包含类的所有东西。
两端循环的引用办法:一端用retain,一端用assign。
6.autorelease
autorelease方法会返回对象本身,会将对象放到一个自动释放池中。
当自动释放池销毁时,会对池子内部的对象做一次release操作。仅仅是release,并不会销毁对象。
<span style="font-size:18px;">autorelease{
<span style="white-space:pre"> </span>Person *p =[ [ [Person alloc] init] autorelease];
}</span>
调用完autorelease方法后,对象的计数器不变。
好处:不用再关心对象释放的时刻,不用再关心什么时候调用release
注意点:占用内存较大的对象不要使用
<span style="font-size:18px;">+(id)person
{
return [[[Person alloc] init] autorelease];
}
</span>
<span style="font-size:18px;">Person *p = [Person person];</span>
+(id)personWithAge:(int)age
{
Person *p = [[[Person alloc] init] autorelease]
p.age = age;// 将传进来的age赋值给对象p里面的age中
return p; // 返回P
}
Person *p = [Person personWithAge:100];