Objective-c - 多个对象的内存管理之三:为某个属性反复赋值同一个对象

本文介绍Objective-C中如何正确处理同一对象的多次赋值问题,避免因不当的内存管理导致僵尸对象错误。通过实例演示了在手动引用计数(MRC)模式下,如何安全地为属性赋值。

/*

 Objective-c - 多个对象的内存管理之三:如果对某个属性反复赋值的是同一个对象,不应该反复的release旧的,retain新的.

 当我们多次为属性赋值相同的对象的时候,就会出现僵尸对象错误.

 

    解决:

        - (void)setCar:(YYCar *)car

         {

            if(_car != car)

         {

            [_car release];

            _car = [car retain];

         }

 

         }

         

        - (void)dealloc

         {

            [_car release];

            [super dealloc];

         }

 

 

 

 

 */

//前提是:关闭ARC,MRC模式下.模拟//小明开车去上学.

#import <Foundation/Foundation.h>


#pragma mark -

#pragma mark 车类的创建

//声明

@interface YYCar : NSObject

{

    NSString *_brand;

}


- (void)setBrand:(NSString *)brand;

- (NSString *)brand;


- (void)run;


//自定义构造方法

- (instancetype)initWithBrand:(NSString *)brand;

+ (instancetype)carWithBrand:(NSString *)brand;


@end


//实现

@implementation YYCar


//重写dealloc方法以监视对象的释放

- (void)dealloc

{

    NSLog(@"%@释放了!", _brand);

    [super dealloc];

}


- (void)setBrand:(NSString *)brand

{

    _brand = brand;

}

- (NSString *)brand

{

    return _brand;

}


- (void)run

{

    NSLog(@"%@在行驶!", _brand);

}


//自定义构造方法

- (instancetype)initWithBrand:(NSString *)brand

{

    if(self = [super init])

    {

        self.brand = brand;

    }

    return self;

}

+ (instancetype)carWithBrand:(NSString *)brand

{

    return [[self alloc] initWithBrand:brand];

}


@end


#pragma mark -

#pragma mark 人类的创建

//声明

@interface YYPerson : NSObject

{

    NSString *_name;

    YYCar *_car;

}


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

- (NSString *)name;


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

- (YYCar *)car;


- (void)drive:(YYCar *)car;


//自定义构造方法

- (instancetype)initWithName:(NSString *)name;

- (instancetype)initWithName:(NSString *)name andCar:(YYCar *)car;


+ (instancetype)personWithName:(NSString *)name;

+ (instancetype)personWithName:(NSString *)name andCar:(YYCar *)car;


@end


//实现

@implementation YYPerson


//重写dealloc方法以监视对象的释放

- (void)dealloc

{

    NSLog(@"%@释放了!", _name);

    //人类对象释放的时候,就代表_car指向的对象不再使用了;

    //不再使用一个对象的时候,应该为其发送一条release消息进行匹配.

    [_car release];

    [super dealloc];

}


- (void)setName:(NSString *)name

{

    _name = name;

}

- (NSString *)name

{

    return _name;

}


//car对象赋值给人对象的_car属性,代表car对象多了一个人使用,所以应该为传入的car对象发送一条retain消息,代表多一个人使用;

//为人对象的车属性赋新值的时候,代表旧对象不再使用,新对象多一个人使用,此时,应该先为就对象发送一条release消息,retain新对象;

- (void)setCar:(YYCar *)car

{

    //如果对某个属性反复赋值的是同一个对象,不应该反复的release旧的,retain新的.

    if(_car != car)

    {

        [_car release];

        _car = [car retain];

    }

}

- (YYCar *)car

{

    return _car;

}


- (void)drive:(YYCar *)car

{

    NSLog(@"%@开着%@去上学!", [self name], [car brand]);

    [car run];

}


//自定义构造方法

- (instancetype)initWithName:(NSString *)name

{

    if(self = [super init])

    {

        self.name = name;

    }

    return self;

}

- (instancetype)initWithName:(NSString *)name andCar:(YYCar *)car

{

    if(self = [super init])

    {

        self.name = name;

        self.car = car;

    }

    return self;

}


+ (instancetype)personWithName:(NSString *)name;

{

    return [[self alloc] initWithName:name];

}

+ (instancetype)personWithName:(NSString *)name andCar:(YYCar *)car

{

    return [[self alloc] initWithName:name andCar:car];

}


@end


#pragma mark -

#pragma mark main函数

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

    

    //人对象的创建及初始化

    YYPerson *xiaoming = [YYPerson personWithName:@"小明"];

    NSLog(@"xiaoming.retainCount = %lu", xiaoming.retainCount);

    

    

    //奔驰车对象的创建及初始化

    YYCar *bz = [YYCar carWithBrand:@"奔驰"];

    NSLog(@"bz.retainCount = %lu", bz.retainCount);

    

    

    

    

    

    //将车对象赋值类人类对象,此时代表车类对象多一个人使用,方法内部为车对象发送了一天retain消息.

    xiaoming.car = bz;

    [xiaoming drive:bz];

    

    bz.brand = @"犇迪";

    //当我们多次为属性赋值相同的对象的时候,就会出现僵尸对象错误.

    //所以如果对某个属性反复赋值的是同一个对象,不应该反复的release旧的,retain新的.

    xiaoming.car = bz;

    

    [xiaoming drive:bz];

    

    [bz release];

    //人对象释放的时候,代表车对象少一个人使用,此时dealloc方法内部为车对象匹配了一条release消息.

    [xiaoming release];

    

    return 0;

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值