// 管理内存有三种方法
// 一:垃圾回收,java常见的管理内存的方法,系统来检测对象是否被使用,是否被释放
// 二:MRC手动管理引用计数,iOS管理内存的方式,程序员通过手动方式来管理对象是否被释放
// 三:ARC自动管理引用计数,基于MRC,系统自动的管理内存,以后我们还是先使用MRC,培养管理内存的习惯
1.
对象被创建出来之后它的引用计数retainCount就变成1
Boy *boy=[[Boy alloc] init];
NSLog(@”%ld”,boy.retainCount);
2015-07-27 19:19:04.268 OC08,09_内存管理[4084:303] 1
// retain:对对象的引用计数+1
[boy retain];
NSLog(@”%ld”,boy.retainCount);
2015-07-27 19:20:01.061 OC08,09_内存管理[4095:303] 2
[boy retain];
[boy retain];
NSLog(@”%ld”,boy.retainCount);
2015-07-27 19:20:01.061 OC08,09_内存管理[4095:303] 4
// release:对对象的引用计数-1
[boy release];
NSLog(@”%ld”,boy.retainCount);
2015-07-27 19:21:12.346 OC08,09_内存管理[4110:303] 3
[boy release];
[boy release];
[boy release];
在Boy.m中
-(void)dealloc{
NSLog(@”对象被释放掉了”);
// 把成员变量里的+1的操作全部减去
[_name release];
[_girls release];
[_hobby release];
[super dealloc];
}
2015-07-27 19:21:12.347 OC08,09_内存管理[4110:303]对象被释放掉了
// 当对象的引用计数1->0的时候,会自动的调用dealloc方法,dealloc才是对应对象释放的方法
// 当对象调用release的时候,它的引用计数是1,这个对象就不在对它的引用计数进行-1操作,而是直接调用dealloc方法,所以我们在访问对象的引用计数还是1
// 如果多次对对象进行释放,会造成过度释放,过度释放也是最常见的内存问题
2.NSString 的对象在全局静态区,它的引用计数是-1,代表正整数的最大值,其他的对象都在堆区
NSArray *arr=@[@”1”,@”2”,@”3”,@”4”];
NSLog(@”%ld”,arr.retainCount);
2015-07-27 19:23:55.669 OC08,09_内存管理[4150:303] 1
NSString *str=@”111111”;
NSLog(@”%ld”,str.retainCount);
2015-07-27 19:23:55.679 OC08,09_内存管理[4150:303] -1
NSMutableString *str2=[NSMutableStringstringWithString:@”1111”];
NSLog(@”%ld”,str2.retainCount);
2015-07-27 19:23:55.679 OC08,09_内存管理[4150:303] 1
NSMutableArray *arr2=[NSMutableArray arrayWithArray:@[@”1”,@”2”,@”3”,@”4”]];
NSLog(@”%ld”,arr2.retainCount);
2015-07-27 19:23:55.680 OC08,09_内存管理[4150:303] 1
NSDictionary *dic=@{@”1”:@”2”,@”3”:@”4”};
NSLog(@”%ld”,dic.retainCount);
2015-07-27 19:23:55.680 OC08,09_内存管理[4150:303] 1
3.release马上回把对象的引用计数-1,但是autorelease会延迟对对象的计数-1
自动释放池:只要对象用autorelease释放会把对象放入到系统的自动释放池中,等出了池子范围,对象引用计数自动-1,这个相当于java的垃圾回收,对象释放由系统来管理
Boy *boy=[[Boy alloc] init];
[boy retain];
[boy retain];
[boy release];
@autoreleasepool {
[boy autorelease];
NSLog(@”%ld”,boy.retainCount);
}
NSLog(@”%ld”,boy.retainCount);
2015-07-27 19:28:40.550 OC08,09_内存管理[4209:303] 2
2015-07-27 19:28:40.550 OC08,09_内存管理[4209:303] 1
4.内存管理的原则:加多少,对应减多少,加减做到平衡
对象的所有权:拥有所有权的对象可以对他进行release
对象如果是我们进行alloc或者retain之后我们就获取了对象的所有权,就可以对对象进行release操作
便利构造器在返回对象的时候会加上一个autorelease,所以用便利构造器创建对象不需要对内存进行管理
id是泛型指针,可以用在任何的方法中,但是instancetype代表实例类型,用在自定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去
5.不可变->可变
(1) NSMutableArray *arr1=[NSMutableArrayarrayWithArray:arr];
(2) NSMutableArray *arr2=[arrmutableCopy];
[arr2 addObject:@”5”];
NSLog(@”%@”,arr2);
2015-07-27 19:31:49.456 OC08,09_内存管理[4276:303] (
1,
2,
3,
4,
5
)
6.系统的类要是实现copy拷贝功能,必须先签订拷贝NSCopying的协议,然后实现对应的方法
不可变的数组字典可以通过mutableCopy转换成可变的数组字典
mutableCopy出来的对象是可变的,copy是不可变的
如果自己的类想要实现copy的功能,就必须先签订NSCopying,然后实现对应的协议方法,initWithZone,之后就可以使用copy功能
copy也可以改变引用计数,但是它改变的是新对象的引用计数,而原先的对象计数不变
当对象放入到容器Array或者字典中,对象会被容器进行一次持有,就是retain一次,它的引用计数会+1,主要是为了防止空指针的问题
等对象从容器中移除掉之后,相应得会-1
-(void)setName:(NSString *)name{
if (_name!=name) {
[_name release];
_name=[name retain];
}
// [name retain];
// [_name release];
// _name=name;
}
7.创建一个类Person
Person.h
import
import “Person.h”
@implementation Person
-(id)initWithName:(NSString *)name
age:(NSInteger)age{
self=[superinit];
if (self) {
self.name=name;
self.age=age;
// _age=age;
// 对象创建之后,里面的数组也会创建好,不用在外面进行创建,避免因为忘了,造成问题
self.arr=[NSMutableArrayarray];
}
return self;
}
+(Person )personWithName:(NSString )name
age:(NSInteger)age{
Person *person=[[Personalloc] initWithName:nameage:age];
return [person autorelease];
}
-(void)dealloc{
[_arr release];
[_name release];
[super dealloc];
}
@end
main.m
Person *per=[[Personalloc] initWithName:@”张三”age:20];
[per.arr addObject:@”1”];
NSLog(@”%@”,per.arr);
2015-07-27 19:31:49.457 OC08,09_内存管理[4276:303] (
1
)