【MRC手动内存管理复习 Objective-C语言】

一、MRC——手动内存管理复习

1.例如,我这儿有一个Car类,当然要先关掉ARC——自动内存管理,否则手动内存管理的方法不能调用,关闭的方法前面已经讲过,在Target的Building Setting里面找到Automatic Reference Count 设置为NO

在Car.h文件中

#import <Foundation/Foundation.h>

@interface Car : NSObject

{

NSString *_name;

int _speed;

}

- (void)setName:(NSString *)name;

- (NSString *)name;

- (void)setSpeed:(int)speed;

- (int)speed;

- (void)run;

@end

2.在Car.m文件中

#import “Car.h”

@implementation Car

- (void)setName:(NSString *)name

{

_name = name;

}

- (NSString *)name

{

return _name;

}

- (void)setSpeed:(int)speed

{

_speed = speed;

}

- (int)speed

{

return _speed;

}

- (void)run

{

NSLog(@“速度为%d的车,在行驶”,_speed);

}

- (void)dealloc

{

NSLog(@“名字为%@的车挂了。。。”,_name);

[super dealloc];

}

@end

3.我这儿还有一个Person类,在Person.h文件中

#import <Foundation/Foundation.h>

#import “Car.h”

@interface Person : NSObject

{

NSString *_name;

Car *_car;

}

- (void)setName:(NSString *)name;

- (NSString *)name;

- (void)setCar:(Car *)car;

- (Car *)car;

- (void)drive;

@end

4.在Person.m文件中

#import “Person.h”

@implementation Person

- (void)setName:(NSString *)name

{

_name = name;

}

- (NSString *)name

{

return _name;

}

- (void)setCar:(Car *)car

{

[_car release];

_car = [car retain];

}

- (Car *)car

{

return _car;

}

- (void)drive

{

[_car run];

}

- (void)dealloc

{

[_car release];

NSLog(@“人挂了。。。”);

[super dealloc];

}

@end

5.在main.m文件中

#import <Foundation/Foundation.h>

#import “Person.h”

int main(int argc, const char * argv[])

{

void (^myBlock1)(void);

myBlock1 = ^void(void){

@autoreleasepool {

Person *fj = [[Person new] autorelease];//1

NSLog(@“fj = %lu”,fj.retainCount);

fj.name = @“凤姐”;

Car *bmw = [[Car new] autorelease];//1

bmw.name = @“bmw”;

NSLog(@“bmw = %lu”,bmw.retainCount);

bmw.speed = 100;

fj.car = bmw;//2

NSLog(@“fj = %lu”,fj.retainCount);

NSLog(@“bmw = %lu”,bmw.retainCount);

[fj drive];

NSLog(@“fj = %lu”,fj.retainCount);

NSLog(@“bmw = %lu”,bmw.retainCount);

[fj drive];

NSLog(@“fj = %lu”,fj.retainCount);

NSLog(@“bmw = %lu”,bmw.retainCount);

Car *benz = [[Car new] autorelease];

benz.name = @“benz”;

NSLog(@“fj = %lu”,fj.retainCount);

NSLog(@“bmw = %lu”,bmw.retainCount);

NSLog(@“benz = %lu”,benz.retainCount);

benz.speed = 400;

fj.car = benz;

NSLog(@“fj = %lu”,fj.retainCount);

NSLog(@“bmw = %lu”,bmw.retainCount);

NSLog(@“benz = %lu”,benz.retainCount);

[fj drive];

NSLog(@“fj = %lu”,fj.retainCount);

NSLog(@“bmw = %lu”,bmw.retainCount);

NSLog(@“benz = %lu”,benz.retainCount);

}

};

myBlock1();

return 0;

}

7.输出:

fj = 1

bmw = 1

fj = 1

bmw = 2

速度为100的车,在行驶

fj = 1

bmw = 2

速度为100的车,在行驶

fj = 1

bmw = 2

fj = 1

bmw = 2

benz = 1

fj = 1

bmw = 1

benz = 2

速度为400的车,在行驶

fj = 1

bmw = 1

benz = 2

名字为bmw的车挂了。。。

名字为benz的车挂了。。。

人挂了。。。

二、总结

1.这里主要是复习MRC:手动内存管理

2.MRC模式下,setter方法要写为release旧的,retain新的

- (void)setCar:(Car *)car

{

[_car release];

_car = [car retain];

}

3.MRC模式下,dealloc方法,要releaseOC对象类型的所有属性

- (void)dealloc

{

[_car release];

NSLog(@“人挂了。”);

[super dealloc];

}

3.dealloc方法最后,需要调用父类的dealloc方法

4.这里还顺便复习了一下block的声明,和赋值

block的声明

void (^myBlock1)(void);

block的赋值

myBlock1 = ^void(void){

//代码块

};

5.这里还顺便复习了一下@autoreleasepool{

Person *fj = [[Person new] autorelease];

}

大括号结束时,会对所有加入到自动释放池的对象发送一个release消息

怎么加入自动释放池

Person *fj = [[Person new] autorelease];

即可

三、还有一个问题,如果旧对象与新对象是同一个对象,会出现什么样的情况

1.例如,Person对象的_car属性的setter方法如下:

- (void)setCar:(Car *)car

{

[_car release];

_car = [car retain];

}

这样确实可以保证在从宝马换车换到奔驰时,宝马可以顺利释放,但如果是从宝马换成宝马呢,也就是说凤姐不是真正的换车,而是还用宝马这辆车呢,例如

Person *fj = [Person new];

fj.name = @“凤姐”;

Car *bmw = [Car new];

bmw.name = @“宝马”;

bmw.speed = 100;

fj.car = bmw;

[fj drive];

[bmw release];

fj.car = bmw;

[fj drive];

[fj release];

这时候,执行到[bmw release]; fj.car = bmw;这两句话的时候,会报僵尸对象错误,因为在bmw被创建的时候,bmw的引用计数器是1,在第一次fj.car = bmw;的时候,bmw的引用计数器被设为2了,在[bmw release];的时候,bmw的引用计数器又为1了,在第二次fj.car = bmw;的时候,是怎么执行的,是不是如下这样执行的:

[_car release];

_car = [car retain];

这时候,在[_car release];的时候,bmw的引用计数器就为0了,还能执行下面的_car = [car retain];吗,不能了,因为car指向的对象是bmw,它已经被释放了,这时候就会报僵尸对象错误,

好了,怎么解决,

是不是我先判断一下_car 和 car是不是都指向bmw啊,如果都指向bmw,那我还用做任何事情吗,不用,如果不都指向bmw,那我怎么样,是不是release旧的,retain新的啊,所以,我这么写

- (void)setCar : (Car *)car{

if(_car != car)

{

[_car release];

_car = [car retain];

}

}

这才是属性是OC对象的时候,setter方法的最终写法,如果属性不是OC对象,例如是int _age;那setter方法就直接赋值就可以了,_age = age;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

清风清晨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值