【setter方法内存管理之二 Objective-C语言】

前言

上一讲,setter方法内存管理之一,主要是讲了setter方法中,先retain,再把retain方法的返回值赋值给下划线属性,这是属性是OC对象时候的事儿。
第二方面呢,是dealloc方法里,先把属性release掉,再调用父类的dealloc方法。
- (void)setCar:(Car *)car
{
_car = [ car retain];
}
- (void)dealloc
{
[ _car release];
NSLog(@“人挂了。。。”);
[ super dealloc];
}
这种方法,还是有Bug的,有什么Bug呢?
1)例如:
Person *p1 = [Person new];
Car *bmw = [Car new];
bmw.speed = 200;
p1.car = bmw;
[p1 drive];
[bmw release];
[p1 drive];
Car *benz = [Car new];
benz.speed = 400;
p1.car = benz;

[benz release];
[p1 release];
}

这时候,你发现,奔驰可以挂,但是宝马没挂,发生了内存泄露,这是怎么回事儿呢?

一、发生内存泄露的原因

1)最重要的是这句代码:
p1.car = benz;
这句话,是把benz的值赋值给p1对象的下划线car属性,这个代表什么:
a benz多了1个人用
b bmw少了1个人用
c 这个时候bmw要release
d 当我们将传入的Car对象赋值给下划线car属性的时候,
代表1:有可能这个下划线car属性本来就已经指向1个对象了吧,所以代表下划线car属性原本指向的对象少1个人使用
代表2:代表传入的对象多1个人使用
代表3:先把旧的release,再把新的retain
所以,我们应该先把下划线car属性原本指向的对象release,再将传入的新对象retain,所以怎么改呢:
- (void)setCar:(Car *)car
{
[_car release];
_car = [car retain];
}
一开始,下划线car属性是nil,调用release方法,不会报错,也没有反应。
然后下划线car属性retain,这时候宝马的引用计数器变为2,然后再赋值,下划线car属性就指向了宝马。
然后,调用p1对象的setCar方法,把宝马换成奔驰。
p1.car = benz;
这时候,第一步先干嘛,是不是下划线car先release啊?这个时候,下划线car指向的谁,是不是宝马啊?所以宝马的引用计数器就变成1,
然后再把参数car ,retain,这个时候,参数car指向的谁,是不是奔驰啊?所以奔驰的引用计数器就变成2,然后再把奔驰赋值给下划线car属性。
最后,
benz release,奔驰引用计数器变成1,
bmw release ,宝马引用计数器变成0,
p1 release,p1引用计数器变成0,它一旦变成0,就销毁,它一旦销毁,就要执行dealloc方法,在dealloc里面,是不是执行了下划线car属性release啊,这个时候,下划线car属性指向的谁,是不是奔驰啊?奔驰release,是不是奔驰的引用计数器变为0了,奔驰也挂了。

二、总结

1.这个时候,我们又改进了我们这个setter方法,其实就两句话:

–(void)setCar:(Car *)car
{
[_car release];
_car = [car retain];
}

2.当1个属性是1个OC对象的时候:

1)setter方法如果为1个对象的这个属性多次赋值的时候,就会发生内存泄露。
2)发生泄露的原因:当为属性赋值的时候,代表两层含义,代表旧对象少1个人用,代表新对象多1个人用,所以按照内存管理原则,应该怎么样,应该release旧的,retain新的。
3)所以,最后setter方法应该怎么写呢:
- (void)setCar:(Car *)car
{
[_car release];
_car = [ car retain];
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风清晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值