关于IOS开发的内存管理的文章已经不少了,所以系统的知识点就不写了,这里我写点平时工做遇到的疑问以及解答作个总结吧,相信也会有人遇到相同的疑问呢,欢迎学习IOS的朋友请加ios技术交流群:190956763,共同窗习,共同进步!html
假如在.h文件里,定义一个变量@property (nonatomic,retain) AController *aController;ios
疑问1:建立对象时候,通常会使用alloc,new,copy或者mutalbeCopy等方法,web
哪一种写法是正确的?安全
A self.aController=[[AController alloc] init];多线程
B self.aController=[[[AController alloc] init] retain];函数
C self.aController=[[[AController alloc] init] autorelease];post
D self->aController=[[AController alloc] init];学习
答案:C,D 引用计数的主要接口alloc,allocwithzone,new(带初始化) 为对象分配内存,retainCount为“1”,并返回此实例,而调用self.aController,self自己有干了活,他把_aController这个变量至关于又retain一下,所以A的retaincount已是2了,已经泄露了!所以不须要B这样retain了,加autorelease的话,就会把刚才新建那块内存自动释放掉的,若是用D话,没有执行aController的setter方法,由于此时retainCount为“1”,因此D也是正确的,C的话也能用,可是不是好的用法ui
疑问2:在dealloc方法中,这么写有问题吗?atom
- (void)dealloc{ [self.aController release]; self.aController = nil; [super dealloc]; }
答案:这里不须要release了,由于self.aController = nil;已经调用了release了,固然也能够这么写
- (void)dealloc{ [self->aController release]; self->aController = nil; [super dealloc]; }
解释:对于set method来讲,用synthesize来让系统帮咱们生成的set方法和以下的相似:
- (void)setAbc:(id)newAbc { if(_abc != newAbc){ [_abc release]; _abc = [newAbc retain]; //是retain仍是copy取决于你property声明时的attributes } }
若是新值和成员相等,就不须要进行重复的赋值了,不等的话,须要把新值赋给成员,同时,成员_abc原来的内容就不须要了,这里要先调用release进行释放。(这个具体的缘由在那本讲Objective-C的书中写的很清楚,请查看)。
所以在这里,调用self.abc = nil;
就等于已经调用了[_abc release]; 和_abc = nil;
self.abc = nil;和[_abc release]; 都不必定释放对象,由于该对象还可能被别的引用,这里的操做的意图就是:别的地方用没用_abc我不知道,在这里的_abc我不用了。
为何release后还要设置nil呢?由于是这样的,若是引用 计数等于0还对该对象进行操做,则会出现内存访问失败,crash,因此尽可能设置为nil,可是单纯设置为nil,若是retaincount不是0的话,内存同样泄露的,所以应该设置nil的时候,先保证变量的retaincount是0了
疑问3:为何有些变量不用考虑retain,release呢?
NSString *str1 = @”constant string”;
str1的retain count是个很大的数字。Objective-C对常量字符串作了特殊处理。
固然,若是你这样建立NSString,获得的retain count依然为1
NSString *str2 = [NSString stringWithFormat:@”123”];
但实际上对于 [NSString stringWithFormat:] 这类构造函数返回的对象都是autorelease的,因此也不用考虑retain,release
疑问4:在ARC的状况下,按说不用本身在考虑release了,为何还会有dealloc方法存在呢?
答案:虽然在ARC下,不用考虑release了,可是咱们可能还要释放一些其余的东西,好比delegate,关闭定时器,关闭gps定位等,另外若是在ARC下,咱们本身不放心,为了安全,本身释放变量也没有什么错误发生!另外不用再调用[super dealloc]了
好比在ARC下,咱们可能会这么写
- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self.closeButtonTimer invalidate]; [self.webView setDelegate:nil]; [self setLocationDetectionEnabled:NO]; }
注意:好比Delegate,若是不在dealloc中释放它,若是页面有多线程的调用,好比开辟个线程从网上down图片子类的,它down下来后须要找这个页面,可是可能用户操做比较快,好比点了后退按钮,这时候页面可能已经销毁了,因而就致使页面崩溃了,因此dealloc中要释放掉delegate
疑问5:怎么能知道哪里内存泄露了呢?
这个就不详细解释了,看相关的帖子说的很详细了
http://www.cocoachina.com/newbie/basic/2012/1204/5242.html
疑问6:声明为IBOutlet属性的,在MRC中应该retain仍是assign?在ARC中应该是strong仍是weak?
在MRC中,应该是retain的,由于IBOutlet自己就是retain的
任何一个被声明为IBOutlet而且在Interface Builder里被链接到一个UI组件的成员变量,会被额外retain一次。
常见的情形如
IBOutlet UILabel *label; |
这个label在Interface Builder里被链接到一个UILabel。此时,这个label的retainCount为2。
因此,只要使用了IBOutlet变量,必定须要在dealloc或者viewDidUnload里release这个变量。
在ARC中,property,咱们将其申明为weak(事实上,若是没有特别意外,除了最顶层的IBOutlet意外,本身写的outlet都应该是weak)。经过加载xib获得的用户界面,在其从xib文件加载时,就已是view hierarchy的一部分了,而view hierarchy中的指向都是strong的。所以outlet所指向的UI对象不该当再被hold一次了。将这些outlet写为weak的最显而易见的好处是你就不用再viewDidUnload方法中再将这些outlet设为nil了(不然就算view被摧毁了,可是因为这些UI对象还在被outlet指针指向而没法释放)。
参考:
http://www.16kan.com/post/214006.html
http://www.ityran.com/archives/1234
疑问7:在ARC在,若是用retain,和用strong有什么区别?
retain关键字在ARC中是依旧可用的,它在ARC中所扮演的角色和strong彻底同样。为了不迷惑,最好在须要的时候将其写为strong,那样更符合ARC的规则。