iOS OC08,09_内存管理
2015-07-27 19:18
411 查看
//管理内存有三种方式, //1.是垃圾回收,java常见的管理内存的方法,系统来检测对象是否被使用,是否被释放 //2.MRC手动管理引用计数,iOS管理内存的方式,程序员通过手动的方式来管理对象是否被释放 //3.ARC自动管理引用计数,基于MRC,系统自动的管理内存,以后我们还是先使用MRC,培养管理内存的习惯
// // Girl.h // OC08,09_内存管理 // // Created by dllo on 15/7/27. // Copyright (c) 2015年 zhozhicheng. All rights reserved. // #import <Foundation/Foundation.h> //1.声明协议 @protocol GirlDelegate <NSObject> @required -(void)married; @optional -(void)cook; @end @interface Girl : NSObject //2.声明代理人属性 @property(nonatomic,assign)id<GirlDelegate>delegate; -(void)getMarry; @end // // Girl.m // OC08,09_内存管理 // // Created by dllo on 15/7/27. // Copyright (c) 2015年 zhozhicheng. All rights reserved. // #import "Girl.h" @implementation Girl -(void)getMarry{ [self.delegate cook]; } @end
// // Boy.h // OC08,09_内存管理 // // Created by dllo on 15/7/27. // Copyright (c) 2015年 zhozhicheng. All rights reserved. // #import <Foundation/Foundation.h> #import "Girl.h" @interface Boy : NSObject<GirlDelegate,NSCopying> -(void)dealloc; +(Boy*)boy; @property(nonatomic,retain)NSString *name; @property(nonatomic,copy)NSString *hobby; @property(nonatomic,retain)Girl *girls; //自定义的初始化方法 -(instancetype)initWithName:(NSString *)name hobby:(NSString *)hobby; +(Boy *)boyWithName:(NSString *)name hobby:(NSString *)hobby; @end // // Boy.m // OC08,09_内存管理 // // Created by dllo on 15/7/27. // Copyright (c) 2015年 zhozhicheng. All rights reserved. // #import "Boy.h" @implementation Boy -(void)cook{ NSLog(@"做饭吃"); } -(void)dealloc{ NSLog(@"对象被释放了"); //把成员变量所有+1操作全部减去 [_name release]; [_girls release]; [_hobby release]; [super dealloc]; } +(Boy*)boy{ Boy *b=[[Boy alloc] init]; return [b autorelease]; } //id是void * //id是泛型指针,可以用在任何方法中,但是instancetype代表实例类型,用在自定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去 //-(instancetype)init{ // Boy *b=[[Boy alloc] init]; // return [b autorelease]; //} - (id)copyWithZone:(NSZone *)zone{ Boy *b=[Boy allocWithZone:zone]; b.hobby=_hobby; b.name=_name; return b; } -(instancetype)initWithName:(NSString *)name hobby:(NSString *)hobby{ [super self]; if (self) { self.name=name; //从直接赋值变成方法赋值 _hobby=hobby; }return self; } +(Boy *)boyWithName:(NSString *)name hobby:(NSString *)hobby{ Boy *b=[[Boy alloc] initWithName:name hobby:hobby]; //写便利构造器最后别忘了autorelease return [b autorelease]; } -(void)setName:(NSString *)name{ if(_name!=name); [_name release]; _name=[name retain]; } @end
对象被创建出来之后他的引用计数retainCount就变成1
Boy *boy=[[Boy alloc] init]; NSLog(@"%ld",boy.retainCount);
结果
2015-07-27 17:47:40.331 OC08,09_内存管理[1562:152231] 1
//对对象的引用计数进行+1的操作
// //retain:对对象的引用计数进行+1Boy *boy=[[Boy alloc] init]; NSLog(@"%ld",boy.retainCount);
[boy retain];
NSLog(@"%ld",boy.retainCount);
[boy retain];
[boy retain];
NSLog(@"%ld",boy.retainCount);
结果
2015-07-27 17:50:13.304 OC08,09_内存管理[1571:153537] 1 2015-07-27 17:50:13.305 OC08,09_内存管理[1571:153537] 2 2015-07-27 17:50:13.305 OC08,09_内存管理[1571:153537] 4
//release:对对象的引用计数进行-1的操作
[boy release]; NSLog(@"%ld",boy.retainCount); [boy release]; [boy release]; [boy release]; NSLog(@"%ld",boy.retainCount);
结果
2015-07-27 17:54:44.714 OC08,09_内存管理[1580:155505] 1 2015-07-27 17:54:44.715 OC08,09_内存管理[1580:155505] 对象被释放了 2015-07-27 17:54:44.715 OC08,09_内存管理[1580:155505] 1
注释
// //如果多次对对象进行释放,会造成过度释放,过度释放也是最常见的内存问题(+1次数小于-1次数) // //[boy release]; // //当对象的引用计数1->0时,会自动调用dealloc方法,dealloc才是对应对象释放的方法 //当对象调用release的时候,他的引用计数是1,这个对象就不再对他的引用计数进行-1操作,而是直接调用dealloc方法,所以我们在访问对象引用计数还是1
几个不同类型retain值
NSArray *arr=@[@"1",@"2",@"3",@"4"]; NSLog(@"%ld",arr.retainCount); NSString *str=@"1111"; NSLog(@"%ld",str.retainCount); NSMutableString *str2=[NSMutableString stringWithString:@"111111"]; NSLog(@"%ld",str2.retainCount); NSDictionary *dic=@{@"1":@"2",@"3":@"4"}; NSLog(@"%ld",dic.retainCount); NSLog(@"%p",str); NSLog(@"%p",str2);
结果
2015-07-27 17:56:31.134 OC08,09_内存管理[1587:156279] 1 2015-07-27 17:56:31.134 OC08,09_内存管理[1587:156279] -1 2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 1 2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 1 2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 0x100002130 2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 0x100112ac0
注释
NSString 的对象在全局静态区,他的引用计数是-1,代表正整数的最大值,其他的对象都在堆区,Boy *boy=[[Boy alloc] init]; [boy retain]; [boy retain]; NSLog(@"%ld",boy.retainCount); //release马上会把对象的引用计数-1,但是autorelease会延迟对对象的计数-1 [boy release]; NSLog(@"%ld",boy.retainCount); [boy autorelease]; NSLog(@"%ld",boy.retainCount); //自动释放池 //只要对象用autorelease释放会把对象放入到系统的自动释放池中,等出了池子范围,对象引用计数自动-1,这个相当于java的垃圾回收,对象释放由系统来管理 @autoreleasepool { [boy autorelease]; NSLog(@"%ld",boy.retainCount); }NSLog(@"%ld",boy.retainCount);
结果
2015-07-27 19:00:44.667 OC08,09_内存管理[1602:162429] 3 2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 2 2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 2 2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 2 2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 1
// 内存管理原则:加多少减多少,加减做到平衡,减多了过度释放,减少了没有得到释放
//对象的所有权:拥有所有权的对象可以对他进行release
Boy *b=[Boy boy]; [b retain]; NSLog(@"%ld",b.retainCount); [b release];
结果
2015-07-27 19:05:11.838 OC08,09_内存管理[1610:164027] 2
//便利构造器在返回对象的时候会加上一个autorelease,所以用便利构造器创建对象不需要对内存进行管理 NSArray *arr1=[[NSArray alloc] initWithObjects:@"1",@"2", nil]; NSArray *arr2=[NSArray arrayWithObjects:@"1",@"2",nil]; [arr1 release];
NSArray *arr=@[@"1",@"2",@"3",@"4"]; NSArray *newArr=[NSArray arrayWithArray:arr]; NSLog(@"%@",newArr); NSLog(@"%ld",arr.retainCount); NSLog(@"%ld",newArr.retainCount);
结果
2015-07-27 19:07:04.008 OC08,09_内存管理[1624:164855] ( 1, 2, 3, 4 ) 2015-07-27 19:07:04.009 OC08,09_内存管理[1624:164855] 1 2015-07-27 19:07:04.010 OC08,09_内存管理[1624:164855] 1
//把一个不可变的变成可变的
NSArray *arr=@[@"1",@"2",@"3",@"4"]; NSMutableArray *arr1=[NSMutableArray arrayWithArray:arr]; NSMutableArray *arr2=[arr mutableCopy]; [arr2 addObject:@"5"]; NSLog(@"%@",arr2); NSDictionary *dic=@{@"1":@"2",@"3":@"4"}; NSMutableDictionary *dic1=[dic mutableCopy]; NSLog(@"%@",dic1);
结果
2015-07-27 19:08:34.111 OC08,09_内存管理[1633:165509] ( 1, 2, 3, 4, 5 ) 2015-07-27 19:08:34.112 OC08,09_内存管理[1633:165509] { 1 = 2; 3 = 4; }
注释
//系统的类要是实现copy功能,必须先签订拷贝NSCopying协议,然后实现对应的方法 //不可变的数组字典可以通过mutableCopy转换成可变的数组字典 //mutableCopy出来的对象可变,copy是不可变的
举例
Girl Boy文件// // Girl.h // OC08,09_内存管理 // // Created by dllo on 15/7/27. // Copyright (c) 2015年 zhozhicheng. All rights reserved. // #import <Foundation/Foundation.h> //1.声明协议 @protocol GirlDelegate <NSObject> @required -(void)married; @optional -(void)cook; @end @interface Girl : NSObject //2.声明代理人属性 @property(nonatomic,assign)id<GirlDelegate>delegate; -(void)getMarry; @end // // Girl.m // OC08,09_内存管理 // // Created by dllo on 15/7/27. // Copyright (c) 2015年 zhozhicheng. All rights reserved. // #import "Girl.h" @implementation Girl -(void)getMarry{ [self.delegate cook]; } @end // // Boy.h // OC08,09_内存管理 // // Created by dllo on 15/7/27. // Copyright (c) 2015年 zhozhicheng. All rights reserved. // #import <Foundation/Foundation.h> #import "Girl.h" @interface Boy : NSObject<GirlDelegate,NSCopying> -(void)dealloc; +(Boy*)boy; @property(nonatomic,retain)NSString *name; @property(nonatomic,copy)NSString *hobby; @property(nonatomic,retain)Girl *girls; //自定义的初始化方法 -(instancetype)initWithName:(NSString *)name hobby:(NSString *)hobby; +(Boy *)boyWithName:(NSString *)name hobby:(NSString *)hobby; @end // // Boy.m // OC08,09_内存管理 // // Created by dllo on 15/7/27. // Copyright (c) 2015年 zhozhicheng. All rights reserved. // #import "Boy.h" @implementation Boy -(void)cook{ NSLog(@"做饭吃"); } -(void)dealloc{ NSLog(@"对象被释放了"); //把成员变量所有+1操作全部减去 [_name release]; [_girls release]; [_hobby release]; [super dealloc]; } +(Boy*)boy{ Boy *b=[[Boy alloc] init]; return [b autorelease]; } //id是void * //id是泛型指针,可以用在任何方法中,但是instancetype代表实例类型,用在自定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去 //-(instancetype)init{ // Boy *b=[[Boy alloc] init]; // return [b autorelease]; //} - (id)copyWithZone:(NSZone *)zone{ Boy *b=[Boy allocWithZone:zone]; b.hobby=_hobby; b.name=_name; return b; } -(instancetype)initWithName:(NSString *)name hobby:(NSString *)hobby{ [super self]; if (self) { self.name=name; //从直接赋值变成方法赋值 _hobby=hobby; }return self; } +(Boy *)boyWithName:(NSString *)name hobby:(NSString *)hobby{ Boy *b=[[Boy alloc] initWithName:name hobby:hobby]; //写便利构造器最后别忘了autorelease return [b autorelease]; } -(void)setName:(NSString *)name{ if(_name!=name); [_name release]; _name=[name retain]; } @end
运行
//Boy类使用Copy的方法 Boy *boy=[Boy boyWithName:@"张阳阳" hobby:@"玩"]; Boy *newBoy=[boy copy]; NSLog(@"%@",newBoy.name); //如果自己的类想要实现copy功能,就必须先签订NSCopying协议,然后实现对应的协议方法,initWithZone,之后就可以使用copy的功能 NSLog(@"%ld",boy.retainCount); NSLog(@"%ld",newBoy.retainCount);
结果
2015-07-27 19:13:02.102 OC08,09_内存管理[1644:168242] 张阳阳 2015-07-27 19:14:15.390 OC08,09_内存管理[1653:168927] 1 2015-07-27 19:14:15.390 OC08,09_内存管理[1653:168927] 1
Boy *boy1=[[Boy alloc] init]; [boy1 retain]; [boy1 retain]; NSLog(@"%ld",boy1.retainCount); NSMutableArray *arr=[NSMutableArray arrayWithObjects:boy1, nil]; NSLog(@"%ld",[arr[0] retainCount]);
结果
2015-07-27 19:14:52.821 OC08,09_内存管理[1660:169279] 3 2015-07-27 19:14:52.822 OC08,09_内存管理[1660:169279] 4
注释
// 当对象放入到容器Array或者字典中,对面会被容器进行一次持有,就是retain一次,他的引用计数会+1,主要是为了防止空指针的问题// //等对象从容器移除掉之后,相应的会-1
Boy *b=[[Boy alloc] init]; Girl *girl=[[Girl alloc]init]; b.girls=girl; NSLog(@"%ld",girl.retainCount); Girl *girl2=[[Girl alloc] init]; b.girls=girl2; NSLog(@"%ld",girl.retainCount);
结果
2015-07-27 19:16:00.235 OC08,09_内存管理[1667:169909] 2 2015-07-27 19:16:00.236 OC08,09_内存管理[1667:169909] 1
一个完整的类写法
// // Person.h // OC08,09_内存管理 // // Created by dllo on 15/7/27. // Copyright (c) 2015年 zhozhicheng. All rights reserved. // #import <Foundation/Foundation.h> @interface Person : NSObject @property(nonatomic,retain)NSMutableArray *arr; @property(nonatomic,copy)NSString *name; @property(nonatomic,assign)NSInteger age; -(id)initWithName:(NSString *)name age:(NSInteger)age; +(Person *)personWithName:(NSString *)name age:(NSInteger)age; @end
// // Person.m // OC08,09_内存管理 // // Created by dllo on 15/7/27. // Copyright (c) 2015年 zhozhicheng. All rights reserved. // #import "Person.h" @implementation Person -(id)initWithName:(NSString *)name age:(NSInteger)age{ self=[super init]; if (self) { self.name=name; self.age=age; //对象创建之后,里面的数组也会创建好,不用在外面进行创建,避免因为忘了,造成问题 self.arr=[NSMutableArray array]; }return self; } +(Person *)personWithName:(NSString *)name age:(NSInteger)age{ Person *per=[[Person alloc] initWithName:name age:age]; return [per autorelease]; } -(void)dealloc{ [_arr release]; [_name release]; //age是栈区的,我们操作的是堆区 } @end
Person *per=[[Person alloc] initWithName:@"张阳阳" age:20]; [per.arr addObject:@"1" ]; NSLog(@"%@",per.arr);
结果
2015-07-27 19:18:09.427 OC08,09_内存管理[1675:171354] ( 1 )
相关文章推荐
- iOS学习笔记--(c基础题9)
- ios申请真机调试(Xcode 5)详细解析
- iOS 创建静态库static library
- IOS中的block的retain循环
- iOS-WebP
- Certificates, Identifiers & Profiles简介以及申请发布证书
- iOS开发-Day10-C的复习
- iOS 获取汉字拼音首字母
- iOS方法和实例变量
- iOS基础
- iOS 各种修饰符的区别汇总
- ios-猜拳游小戏的实现
- iOS Notification 通知中心
- IOS开发小tip
- 在iOS 7中使用storyboard(part 1)
- IOS开发单元格自定义方法之一
- IOS手势操作(拖动、捏合、旋转、点按、长按、轻扫、自定义)
- IOS-NSRunLoop
- ios 判断小数点. 后几位 && 小数点后有数据显示数据,没有则不显示数据
- 我的iOS工程结构