OC学习_8_内存管理_MRC

来源:互联网 发布:2016淘宝晚会 编辑:程序博客网 时间:2024/06/05 15:34

======文档更新状态=====
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
原创粉丝点击