OC内存管理
1.方法内存管理
/*
1. OC的内存管理,管的是什么
2.answer is 引用计数 reference counting
//有一个方法可以看到我们一个对象目前的引用计数(只是个参考,不同情况下,这个数与实际情况会有出入)
*/
1、dealloc和release有什么不同,都是干什么的
dealloc 是释放内存的意思,release是使得引用计数减1.
释放内存会使得引用计数减为0,而引用计数减1不一定会使得内存释放。
当引用计数减到0的时候,系统自发调用dealloc方法释放内存。
2、什么关键字会使得引用计数加1
retain、new、copy、alloc。
3、什么关键字会使得引用计数减1
release、autorelease、self.属性 = nil
//对象用完了没有及时释放(把引用计数减到0),我们就称合格对象所指的内存泄露了。
//对象已经释放之后(引用计数减为0),我们还调用这个对象(还release),就崩了,我们称这个对象已经释放了还调用(过度释放)。
/*
1.内存管理管理的是引用计数
2.当一个对象的引用计数大于0时,这个对象可以使用
3.当一个对象的引用计数减为0时,这个对象就会调用自身的dealloc方法释放,然后就不能用了。
4.可以通过alloc、retain、copy、new这些方法让一个对象的引用计数+1.
5、可以通过release、autoRelease、 这些方法让一个对象的引用计数-1.
*/
human *my = [human alloc];
//1.使用alloc申请一块内存生成一个human对象。
[my pp];
NSLog(@"%@",my);
NSLog(@"%lu",[my retainCount]);
//retainCount 可以调用他那个对象的引用计数。
//关键:当一个对象的引用计数大于0时,这个对象的内存可以被使用;
//关键:当等于0 时,这个对象 释放,这段内存就不能用了。
//2.如何让一个对象的引用计数发生改变。
//2.1增加
[my retain];//retain是个关键词,会使得被retain的对象的引用计数+1.
[my pp];
NSLog(@"%lu",[my retainCount]);//2
//2.2减少
[my release];//release是一个关键词,会使得被release的对象应用技术减1.
[my pp];
// [my release];
// [my pp];因为my的内存引用计数已经减为0了,所以my指向的内存已经调用自己的dealloc方法释放掉了,所以我们的内存会crash。
//[my release]; 这个现在也不能调,因为引用计数已经减为0 了,所以my指向的内存已经调用自己的dealloc方法释放掉了,所以再减就是过度释放了,就会crash崩掉。
//sleep(10);
NSLog(@"%lu",[my retainCount]);
NSString *str = [[NSString alloc] initWithString:@"a"];
NSLog(@"%@",str);
NSString *str1 = [NSString stringWithFormat:@"a"];
//当使用类方法创建出来的对象,他的引用计数也依然是1,这种类方法创建出来的对象的这一次的1的引用计数,不需要我们管理。
NSLog(@"%@",str1);
//[str1 release];不用,这个1会由系统自己管理,当这个对象除了他的生命周期后,会自动release -1.
NSArray *arr2 = [[[NSArray alloc] initWithObjects:@"", nil] autorelease];
//在一个alloc出来的对象后面加上autorelease,就意味着这一次alloc出来的引用计数1有这个autorelease来管理,不用手动管理。
//arr4不用的时候,不用管
//autorelease管的,但是什么时候这个autorelease起作用(什么时候采取减1),出了这个对象所在的自动释放池,才会调用这个对象的autorelease,慎用。
//autorelease 用时:一般我们给一个方法有返回值的时候,这个返回值我们写成:[返回值 autorelease];
TempClass *temp = [TempClass alloc];
[temp sayHello];
[temp release];//引用计数减1
TempClass *t1 = [TempClass alloc];
//t1 引用计数 可用
NSArray *arr = [NSArray arrayWithObjects:t1, nil];
//t1 引用计数2 可用‘
//当我们把一个对象放进数组等集合中的时候(调用类方法都不需要release)(addobject:addSubView),这个对象的引用计数会自动加1 ,但这个1不需要我们管理。
//第一种情况:这个对象从集合中移除了,自动调用release吧add进去时候的+1进行—1操作
//第二种情况:这个集合被释放了,集合里面的所有元素都会执行-1操作,吧add进去的时候的+1进行-1
NSLog(@"%@",arr);
// [t1 release];
// //引用计数-1,但是归数组管的那个1还在,所以还能用。
// NSLog(@"%@",t1);
NSArray *arr1 = [[NSArray alloc] initWithObjects:t1, nil];
//t1 引用计数=3;其中1需要自己管对t1的那个alloc,剩下两个引用计数分别由arr和arr1自动管理。
//arr 引用计数=1, 不需要管理 类方法
//arr1 引用计数=1 ,需要管 alloc方法。
SeconClass *second = [SeconClass alloc];
[second doSomething];
[second release];
thirdClass *third = [thirdClass alloc];
[third thirdSay];
NSString *thirdBackStr = [[NSString alloc] initWithString:[third thirdWant]];
[third release];
NSLog(@"%@",thirdBackStr);
[thirdBackStr release];
2.内存管理工具 ---- instruments
用内存管理工具可以帮助我们查看引用计数的加减次数,能看到是在哪里进行的加减,但这个跨多个类的时候可能不准,仅作参考。
3.属性的内存管理
//属性的修饰符:retain,assign,copy;
(.h文件中)
@property(nonatomic,retain)NSString *name;
//retain表示这个属性在指向新内存时,会把它之前指的那块内存执行release(-1)操作,然后对新指向的内存执行retain(+1)操作。
@property(nonatomic,assign)NSString *age;
//assign表示这个属性指了一下
@property(nonatomic,copy)NSString *sex;
//copy表示这个属性在指向新内存时,会把它之前申请的那块内存执行release(-1)操作,然后按照新指向的那块内存的内容自己申请一块内存,里面存的内容与新指向的那块内存一样。
//什么时候用:
//当我这个属性不想管理内存的时候,就用assign(防止重复引用)
//当我们希望可以持有被指的内存的时候,就用retain(变成自己的了,自己+1,只要自己不release,永远能用。自己改了,被指的也改了)。
//当我们希望持有,又不想影响被指的内存的时候,就用copy(变成自己的(自己按照被指的对象申请内存),自己+1,只要自己不release,永远能用。自己改了,不影响被指的。)
(.m文件中 )执行dealloc方法
-(void)dealloc
{
//必须重写dealloc的时候,是这个类有retain,copy属性的时候。
[self.name release];
[self.sex release];
[super dealloc];
}