将项目设置成MRC的项目:
Build Setting——选Levels——搜索Objective-C Automatic Reference Counting,将其改为NO
1、内存管理/引用技术:
定一个总的方针政策吧:
自己创建的对象,自己持有;(自己养的狗,肯定自己遛呀)
非自己创建的对象也可以自己持有;(不是自己养的就不能遛了?)
不再需要自己持有的对象时释放;(利用完了就干掉)
非自己持有的对象,无法释放;(动别人家的狗,咬不死你)
内存管理的四个关键词:生成、持有、释放、废弃!与之对应的OC的主要方法:
生成并持有:alloc、new、copy、mutablecopy
非自己生成想持有:retain
释放:release
废弃:dealloc
调用alloc和retain方法后,引用计数+1;release执行后,引用计数-1;引用计数为0后,调用dealloc进行释放!
接下来逐个分析一下各个方针政策:
自己生成的对象,自己所持有:(alloc、new、copy、mutablecopy)
使用以下名称开头的方法名意味着自己生成的对象只有自己持有(注意是“用以下名称开头的方法名”):
- alloc
- new
- copy
- mutableCopy
到这里,一些有强迫症的同志估计就要问了,难道所有以这几个词为开头的方法生成的对象都是自己持有吗?
这里,我就要指出一个我们猿狮们都听说过的一个词汇——驼峰命名法。是的,你没有听错,所有以驼峰命名法命名,且使用了上诉几个词汇开头的方法生成的对象都是自己持有的,而像什么copying,mutableCopyed等这种以假乱真、冒名顶替的方法,对它嗤之以鼻就好了。
非自己生成的对象,自己也能持有:(retain)
那想要持有其他人的对象(肯定不是自己持有的)怎么办呢?使用retain。别人家养的狗,还不能套吗?retain就是那套狗的工具,套上了就是你的了。
不再需要自己持有的对象时释放:(release、autorealease)
该放手时就放手。release
死后也要撒手。autorelease
release 立即释放
autorelease 对象在超出指定的生存范围时,自动释放池pool结束时调用release释放。这里要特别说明一下,系统所有类方法创建的对象都是调用过autorelease实例方法的,这样就不会引起有内存没有泄露的情况
非自己持有的对象,无法释放
这个很好理解了,不是自己的对象,肯定不能自己释放的。如果在程序中释放了非自己持有的对象将导致崩溃,同样的,重复释放也会导致崩溃。
用一波代码展示一下这节的内容:
- (void)retainCount {
//自己生成的对象,自己持有
NSObject * obj1 = [NSObject new];
printf("obj1 retainCount = %lu\n",(unsigned long)obj1.retainCount); // 1
[obj1 release];
//非自己生成的对象,也可以自己持有
NSObject * obj2 = [NSObject new];
printf("obj2 retainCount = %lu\n",(unsigned long)obj2.retainCount); //1
NSObject * obj3 = [obj2 retain];
printf("obj2 retainCount = %lu\n",(unsigned long)obj2.retainCount); //2
printf("obj3 retainCount = %lu\n",(unsigned long)obj3.retainCount); //2
[obj2 release];
printf("obj2 retainCount = %lu\n",(unsigned long)obj2.retainCount); //1
printf("obj3 retainCount = %lu\n",(unsigned long)obj3.retainCount); //1
[obj3 release];
//obj2和obj3是命运共同体,实际上他们就是别名的作用,所以他们的引用计数一直都是一样的
NSObject * test = [self objc]; //这里objc对象是存在的,但是test不持有objc的。
printf("test retainCount = %lu\n",(unsigned long)test.retainCount); //1
// [test release]; //释放自己不持有的对象,这里会导致崩溃
NSObject * test2 = [[self objc] retain]; //非自己生成的对象只能通过retain才能持有
printf("test2 retainCount = %lu\n",(unsigned long)test2.retainCount); //2
[test2 release];
printf("test2 retainCount = %lu\n",(unsigned long)test2.retainCount); //1
//到了这里实际上objc的引用计数还有1,而这个引用计数就是通过函数的autorelease在之后释放的。
}
- (NSObject * )objc{
NSObject * objc = [[NSObject alloc]init];
printf("objc retainCount = %lu\n",(unsigned long)objc.retainCount); //1
//autorelease 不立即释放,
return [objc autorelease];
}
网友评论