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================
- OC学习_8_内存管理_MRC
- OC学习--内存管理
- OC学习----内存管理
- OC学习笔记之OC内存管理
- OC语言学习-内存管理
- OC内存管理学习感悟
- IOS学习 -- OC内存管理
- my学习OC--内存管理
- OC学习笔记——内存管理
- OC学习那些事:内存管理
- oc学习之旅:内存管理1
- oc学习之旅:内存管理
- 黑马程序员 OC------内存管理学习
- oc学习笔记(八)内存管理
- OC学习笔记——内存管理
- OC语言学习 (七) 内存管理
- OC学习笔记(6)内存管理
- OC学习笔记七---内存管理一
- Java实例变量、类变量与局部变量
- leetcode -- Maximum Product of Word Lengths -- 重点
- Android的selector,背景选择器
- Windows下 Android Studio中获取SHA1的方法
- javascript 浏览器调用原理
- OC学习_8_内存管理_MRC
- Codeforces 597C Subsequences dp + 树状数组
- 黑马程序员——Java语言基础(下)
- Linux查看系统信息的一些命令及查看已安装软件包的命令(转)
- Redis和MongoDB原理简析
- eclipse中 将java项目转换为web项目
- oracle VPD
- 数据结构学期学习总结
- Day0-纠结,思念,与未来