内存管理
2015-07-27 22:12
309 查看
管理内存有三种方式
MRC手动管理规则
retain:对对象的引用计数+1
release:对对象的引用计数-1
NSString: 的对象在全局静态区,它的引用计数是-1, 代表了正整数的最大值,其他对象都在堆区
自动释放池
内存管理的原则: 加多少,对应减多少,加减做到平衡
对象的所有权: 拥有所有权的对象可以对他进行release
便利构造器在返回对象的时候会加上一个 autorelease ,所以用便利构造器创建对象不需要进行内存管理
id是泛型指针,可以用在任何方法中,但是instancetype代表实例类型,用在自定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去
当对象放入到容器Array或字典中, 对象会被容器进行一次持有,就是retain一次,他的引用计数就会+1, 主要防止空指针的问题.
等对象从容器中移除掉之后,相应的会-1.
copy
 属性的语义特性及使⽤用范围
dealloc
构造器管理内存
1:垃圾回收,java常见的管理内存的方法,系统来检测对象是否被回收使用,是否被释放. 2:MRC手动管理引入计数,iOS管理内存的方式,程序员通过手动的方式来管理对象是否被释放. 3:ARC自动管理引入计数,基于MRC,系统自动管理内存. *以后我们还是先使用MRC,培养管理内存的习惯.
MRC手动管理规则
// 对象被创建出来之后他的引用计数retainCount就变成了1 Boy *boy = [[Boy alloc] init]; NSLog(@"%ld", boy.retainCount);
retain:对对象的引用计数+1
Boy *boy = [[Boy alloc] init]; [boy retain]; NSLog(@"%ld", boy.retainCount);
release:对对象的引用计数-1
Boy *boy = [[Boy alloc] init]; NSLog(@"%ld", boy.retainCount); [boy retain]; NSLog(@"%ld", boy.retainCount); [boy release]; NSLog(@"%ld", boy.retainCount); // 当对象的引用对象计数1->0的时候,会自动调用dealloc,dealloc才是对应对象释放的方法 [boy release]; // 当对象调用release的时候, 它的引用计数是1,这个对象就不在对它的引用计数进行-1操作,而是直接调用dealloc方法,所以我们在访问对象的引用计数还是1 NSLog(@"%ld", boy.retainCount); // 如果多次对对象进行释放,会造成过度释放,过度释放也是最常见的内存问题 [boy release];
NSString: 的对象在全局静态区,它的引用计数是-1, 代表了正整数的最大值,其他对象都在堆区
NSString *str = @"111"; NSLog(@"%ld", str.retainCount); // 对于NSString, retain 和 release 没有用
自动释放池
// 只要对象用autoreleasepool 释放会把对象放入到系统的自动释放池中,等出了池子的范围,对象引用计数自动-1,这相当于java的垃圾回收,对象释放有系统来管理
// release 马上会把对象的引用计数-1,但是 autorelease 会延迟对对象的计数-1
Boy *boy = [[Boy alloc] init]; [boy retain]; NSLog(@"%ld", boy.retainCount);
@autoreleasepool {
[boy autorelease];
NSLog(@"%ld", boy.retainCount);
}
NSLog(@"%ld", boy.retainCount);
内存管理的原则: 加多少,对应减多少,加减做到平衡
对象的所有权: 拥有所有权的对象可以对他进行release
便利构造器在返回对象的时候会加上一个 autorelease ,所以用便利构造器创建对象不需要进行内存管理
NSArray *arr1 = [[NSArray alloc] initWithObjects:@"1", @"2", nil]; NSArray *arr2 = [NSArray arrayWithObjects:@"2", @"3", nil]; [arr1 release]; // arr2 便利构造器创建的对象,在main.m文件里不需要进行内存管理
id是泛型指针,可以用在任何方法中,但是instancetype代表实例类型,用在自定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去
当对象放入到容器Array或字典中, 对象会被容器进行一次持有,就是retain一次,他的引用计数就会+1, 主要防止空指针的问题.
等对象从容器中移除掉之后,相应的会-1.
Boy *boy1 = [[Boy alloc] init]; [boy1 retain]; NSLog(@"%ld", boy1.retainCount); NSMutableArray *arr = [NSMutableArray arrayWithObjects:boy1, nil]; NSLog(@"%ld", boy1.retainCount); [arr removeObjectAtIndex:0]; NSLog(@"%ld", boy1.retainCount);
copy
// 系统的类要是实现copy拷贝的功能,必须先签订拷贝NSCopying的协议,然后实现对应的方法 // 不可变的数组方法字典可以通过mutableCopy转换成可变的数组字典 // mutableCopy出来的对象是可变的,Copy出来的对象是不可变的 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 *muDic = [dic mutableCopy]; NSLog(@"%@", muDic); ---------------------------------------------------------- // 如果自己的类想要实现copy的功能,就必须先签订NSCopying,然后实现对应的协议方法,initWithZone,之后就可以用copy的功能 Boy *boy = [Boy boyWithName:@"腾飞" hobby:@"吃"]; Boy *newBoy = [boy copy]; NSLog(@"%@", newBoy.name); // boy.h文件 @interface Boy : NSObject<NSCopying> @property(nonatomic, retain)NSString *name; @property(nonatomic, copy)NSString *hobby; -(instancetype)initWithName:(NSString *)name hobby:(NSString *)hobby; +(Boy *)boyWithName:(NSString *)name hobby:(NSString *)hobby; @end // boy.m文件 -(instancetype)initWithName:(NSString *)name hobby:(NSString *)hobby { self = [super init]; if (self) { self.name = name; self.hobby = hobby; } return self; } +(Boy *)boyWithName:(NSString *)name hobby:(NSString *)hobby { Boy *boy = [[Boy alloc] initWithName:name hobby:hobby]; // 写便利构造器最后别忘了 autorelease return [boy autorelease]; } -(id)copyWithZone:(NSZone *)zone { Boy *b =[Boy allocWithZone:zone]; b.hobby = _hobby; b.name = _name; return b; }
 属性的语义特性及使⽤用范围
//assign下的属性内部实现 //setter方法 @property(nonatomic,assign)NSString *name; - (void)setName:(NSString *)name _name = name; } //getter方法 - (NSString *)name{ return _name; 如果在 main.m中 按照下面方式去书写会出现问题 NSString *name = [[NSString alloc] initWithFormat:@”张三”]; Person *p = [[Person alloc]init]; [p setName:name]; [name release]; NSLog(@”%@”,[p name]); // 野指针异常 [p release]; ---------------------------------------------------------- //retain下的属性内部实现  //setter方法 @property(nonatomic,retain)NSString *name; - (void)setName:(NSString *)name { if(_name != name){ [_name release]; _name = [name retain]; } } //getter方法 - (NSString *)name { return [[_name retain]autorelease]; } //main.m中 NSString *name = [[NSString alloc] initWithFormat:@”张三”]; Person *p = [[Person alloc]init]; [p setName:name]; [name release]; NSLog(@”%@”,[p name]); NSString *newName = [[NSString alloc]initWithFormat:@”李四”]; [p setName:newName]; [newName release]; NSLog(@”%@”,[p name]); [p release]; ---------------------------------------------------------- // copy下的属性内部实现 // setter方法 @property(nonatomic,copy)NSString *name; - (void)setName:(NSString *)name { if(_name != name){ [_name release]; _name = [name copy]; } } // getter方法 - (NSString *)name{ return [[_name retain]autorelease]; } // main.m中 NSString *name = [[NSString alloc] initWithFormat:@”张三”]; Person *p = [[Person alloc]init]; [p setName:name]; [name release]; NSLog(@”%@”,[p name]); NSString *newName = [[NSString alloc]initWithFormat:@”李四”]; [p setName:newName]; [newName release]; NSLog(@”%@”,[p name]); [p release];
dealloc
dealloc是NSObject的⼀一个实例⽅方法,与alloc对应,⽤用于回收开辟的内 存空间 // Person.m中, 如何使⽤用dealloc (void)dealloc { [_name release];//释放setter方法泄露的实例变量 [super dealloc]; }
构造器管理内存
-(id)initWithName:(NSString *)name age:(NSInteger)age { self = [super init]; if (self) { self.name = name; self.age = age; // _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]; }
相关文章推荐
- php编程冒泡排序
- MyBatis知多少(20)MyBatis读取操作
- Tomcat服务器在Mac平台和windows平台上的搭建
- 莫比乌斯反演
- free delete malloc new(——高品质量程序设计指南第16章)
- 平衡二叉树
- cuDNN: efficient Primitives for Deep Learning 论文阅读笔记
- [3D游戏开发]Early ZBuffer
- UI中 View、Label的方法
- 产生冠军
- KnockoutJS的使用及分析
- HDU 1233 首字母变大写
- LeetCode Everyday --226
- Linux系统调用及用户编程接口(API)
- 程序员必读的六本书
- SCOI2009生日蛋糕
- 在Activity的onCreate方法中显示PopupWindow导致异常的原因分析及解决方案
- 第一百一十六天 how can I 坚持
- Android(java)学习笔记134:Handler用法总结和秒表案例
- error: variably modified 'table' at file scope