OC学习_8_内存管理_MRC

======文档更新状态=====
2015-12-21:发布

==================

day08-[2015-12-21]
一、MRC(手动引用计数、手动内存管理)
1.内存管理机制:每个对象都有一个引用计数器retainCount,用来记录堆空间中的对象在栈中有多少指针指向,一旦没有指针指向该空间,则释放
2.Xcode6默认使用ARC,设置automatic reference counting为NO开启MRC
3.过程:
A。新建对象时,retainCount(以下简称RC)被置为1;
B。调用retain方法,RC加1;
C。调用release方法,RC减1;当RC为1时调用release方法,则不再减1,而是直接调用对象的dealloc方法进行释放
4.原则:
A。谁创建谁release
B。谁retain谁release
C。release后立即置为nil,否则在开启“Zombie”模式时会报错
D。不要手动调用dealloc
5.dealloc重写要求:在MRC下,最后一定要有[super dealloc];将父类部分的释放交给父类去做

//  YYPerson.h


#import <Foundation/Foundation.h>

@interface YYPerson : NSObject
@property (nonatomic,copy)NSString* name;
@property (nonatomic,assign)int age;
@end
//  YYPerson.m


#import "YYPerson.h"

@implementation YYPerson
-(void)dealloc{
    NSLog(@"Person %@ dealloc.",_name);
    [super dealloc];
}
@end
//  main.m


#import "YYPerson.h"

int main_person(int argc, const char * argv[]) {
    YYPerson* p1=[YYPerson new];
    p1.name=@"mike";
    NSLog(@"p1.rc:%lu",p1.retainCount);//1
    YYPerson* p2=[p1 retain];
    NSLog(@"p2.rc:%lu,p1.rc:%lu",p2.retainCount,p1.retainCount);//2,2
    YYPerson* p3=[p2 retain];
    NSLog(@"p2.rc:%lu,p3.rc:%lu",p2.retainCount,p3.retainCount);//3,3
    [p3 release];
    p3=nil;
    NSLog(@"p2.rc:%lu,p3.rc:%lu",p2.retainCount,p3.retainCount);//2,2
    [p2 release];
    p2=nil;
    NSLog(@"1.p2.rc:%lu,p1.rc:%lu",p2.retainCount,p1.retainCount);//1,1
    [p1 release];
    p1=nil;
    NSLog(@"2.p2.rc:%lu,p1.rc:%lu",p2.retainCount,p1.retainCount);//1,1
    return 0;
}

二、MRC下的对象嵌套
1.对象嵌套:在一个类中包含另一个类的对象指针,例如:代理模式中主类Manager的代理delegate(id<代理协议>类型)、圆形Circle里的圆心cener(Point类型)
2.MRC下的内存分析:command+shift+B
如果有提示(关键词leak),则很有可能发生内存泄露(不是绝对的);如果没有提示,则可能性较小(也是有泄露可能的)
3.对象嵌套的内存问题(以Hero和Weapon为例)
A.嵌套对象变成僵尸或无法释放,解决:在给嵌套对象指针赋值时使用retain方法,在释放包含嵌套对象的dealloc方法中release
B.改变嵌套对象指针指向的地址(如Hero更换Weapon),解决:改写setter,判断当前指针是否与新指针相同,如果相同什么都不做;如果不同,先将当前指针release,再通过retain获取新指针

//  YYWeapon.h


#import <Foundation/Foundation.h>

@interface YYWeapon : NSObject
{
    @private
    NSString* _name;
}
-(void)setName:(NSString*)name;
-(NSString*)name;
-(instancetype)initWithName:(NSString*)name;
//+(instancetype)weaponWithName:(NSString*)name;

@end
//  YYWeapon.m


#import "YYWeapon.h"

@implementation YYWeapon
-(void)setName:(NSString *)name{
    _name=[name copy];
}

-(NSString *)name{
    return _name;
}

-(instancetype)initWithName:(NSString *)name{
    if (self=[super init]) {
        self.name=name;
    }
    return self;
}

//+(instancetype)weaponWithName:(NSString *)name{
//    return [[self alloc]initWithName:name];
//}

-(void)dealloc{
    NSLog(@"Weapon %@ dealloc.",_name);
    [super dealloc];
}

-(NSString *)description{
    return [NSString stringWithFormat:@"Weapon(%@)",_name];
}
@end
//  YYHero.h


#import "YYWeapon.h"

@interface YYHero : NSObject
{
    @private
    NSString* _name;
    YYWeapon* _weapon;
}

-(void)setName:(NSString*)name;
-(NSString*)name;
-(void)setWeapon:(YYWeapon*)weapon;
-(YYWeapon*)weapon;
-(instancetype)initWithName:(NSString*)name weapon:(YYWeapon*)weapon;
//+(instancetype)heroWithName:(NSString*)name weapon:(YYWeapon*)weapon;

@end
//  YYHero.m


#import "YYHero.h"

@implementation YYHero
-(void)setName:(NSString *)name{
    _name=[name copy];
}

-(NSString *)name{
    return _name;
}
-(void)setWeapon:(YYWeapon *)weapon{
    if (_weapon!=weapon) {
        [_weapon release];
        _weapon=[weapon retain];
    }
}

-(YYWeapon *)weapon{
    return _weapon;
}

-(instancetype)initWithName:(NSString *)name weapon:(YYWeapon *)weapon{
    if (self=[super init]) {
        self.name=name;
        self.weapon=weapon;
    }
    return self;
}

//+(instancetype)heroWithName:(NSString *)name weapon:(YYWeapon *)weapon{
//    return [[self alloc]initWithName:name weapon:weapon];
//}

-(void)dealloc{
    NSLog(@"Hero %@ with %@ dealloc.",_name,_weapon.name);
    [_weapon release];
    [super dealloc];
}

-(NSString *)description{
    return [NSString stringWithFormat:@"Hero %@ using %@",_name,_weapon];
}
@end
//  test_hero1.m


#import "YYHero.h"

int main_hero1(){
//    YYWeapon* sword=[YYWeapon weaponWithName:@"Yitian"];
//    YYHero* zhang=[YYHero heroWithName:@"Zhang" weapon:sword];

    YYWeapon* sword=[[YYWeapon alloc]initWithName:@"Yitian"];
    YYHero* zhang=[[YYHero alloc ]initWithName:@"Zhang" weapon:sword];
    NSLog(@"%@",zhang);
    [sword release];
    NSLog(@"%@",zhang);
    [zhang release];
    return 0;
}
//  test_hero2.m


#import "YYHero.h"

int main_hero2(){
    YYWeapon* sword=[[YYWeapon alloc]initWithName:@"Yitian"];
    YYWeapon* knife=[[YYWeapon alloc]initWithName:@"Tulong"];
    YYHero* zhang=[[YYHero alloc ]initWithName:@"Zhang" weapon:sword];

    NSLog(@"%@",zhang);
    zhang.weapon=sword;
    NSLog(@"After change weapon:%@",zhang);
    [sword release];
    [knife release];
    [zhang release];
    return 0;
}

三、和MRC相关的属性修饰符
1.assign
A。基本类型一定使用assign
B。对象指针使用时表示不修改引用计数
2.retain
A。仅用于OC对象指针或id类型
B。在赋值时,自动调用retain方法;如果已经指向旧的对象指针,则会先调用旧指针的release
C。必须在dealloc中调用该属性的release方法

//  YYSkill.h


#import <Foundation/Foundation.h>

@interface YYSkill : NSObject
@property (nonatomic,copy)NSString* name;

@end
//  YYSkill.m

#import "YYSkill.h"

@implementation YYSkill
-(NSString *)description{
    return [NSString stringWithFormat:@"%@",_name];
}

-(void)dealloc{
    NSLog(@"Skill %@ dealloc.",_name);
    [super dealloc];
}
@end
//  YYMonster.h


#import "YYSkill.h"

@interface YYMonster : NSObject
@property (nonatomic,copy)NSString* name;
@property (nonatomic,retain)YYSkill* skill;
@end
//  YYMonster.m


#import "YYMonster.h"

@implementation YYMonster
-(NSString *)description{
    return [NSString stringWithFormat:@"Monster %@ has %@ skill.",_name,_skill.name];
}

-(void)dealloc{
    [_skill release];
    NSLog(@"Monster %@ dealloc.",_name);
    [super dealloc];    
}
@end
//  test_monster.m


#import "YYMonster.h"
int main(){
    YYSkill* sk=[YYSkill new];
    sk.name=@"打狗棒";
    YYSkill* sk2=[YYSkill new];
    sk2.name=@"十八掌";
    YYMonster* mons=[YYMonster new];
    mons.name=@"洪七";
    mons.skill=sk;//2
    NSLog(@"mons:%@",mons);
    mons.skill=sk2;
    NSLog(@"mons:%@",mons);
    [sk release];
    [sk2 release];
    [mons release];
    return 0;
}

==========EOF================

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值