ARC下可以重寫dealloc方法并在viewController被釋放后自動(dòng)調(diào)用,重寫該方法時(shí)不能顯式調(diào)用[super dealloc],因?yàn)橄到y(tǒng)會(huì)自動(dòng)幫你調(diào)用父類的dealloc方法。
控制器在被pop后移出棧后會(huì)被釋放,但有些時(shí)候會(huì)發(fā)現(xiàn)控制器出棧的時(shí)候不會(huì)調(diào)用dealloc方法,歸根結(jié)底,是因?yàn)楫?dāng)前控制器被某個(gè)對(duì)象強(qiáng)引用了,控制器的引用計(jì)數(shù)不為0,系統(tǒng)無(wú)法幫你釋放這部分內(nèi)存。原因大致有以下幾點(diǎn):
控制器中NSTimer沒(méi)有被銷毀
當(dāng)viewController中存在NSTimer時(shí),需要特別注意,當(dāng)調(diào)用
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES]
時(shí),因?yàn)?target:self ,也就是引用了當(dāng)前viewController,導(dǎo)致控制器的引用計(jì)數(shù)加1,如果沒(méi)有將這個(gè)NSTimer 銷毀,它將一直保留該viewController,無(wú)法釋放,也就不會(huì)調(diào)用dealloc方法。所以,需要在viewWillDisappear之前需要把控制器用到的NSTimer銷毀。
[timer invalidate]; // 銷毀timer
timer = nil; // 置nil
viewController中的代理不是weak屬性
例如@property (nonatomic, weak) id delegate;代理要使用弱引用,因?yàn)樽远x控件是加載在視圖控制器中的,視圖控制器view對(duì)自定義控件是強(qiáng)引用,如果代理屬性設(shè)置為strong,則意味著delegate對(duì)視圖控制器也進(jìn)行了強(qiáng)引用,會(huì)造成循環(huán)引用。導(dǎo)致控制器無(wú)法被釋放,最終導(dǎo)致內(nèi)存泄漏。
viewController中block的循環(huán)引用
在ARC下,block會(huì)把它里面的所有對(duì)象強(qiáng)引用,包括當(dāng)前控制器self,因此有可能會(huì)出現(xiàn)循環(huán)引用的問(wèn)題。比如viewController中有個(gè)block屬性,在block中又強(qiáng)引用了self或者其他成員變量,那么這個(gè)viewController與自己的block屬性就形成循環(huán)引用,導(dǎo)致viewController無(wú)法釋放。
// ARC enabled
/************** MyObject Class **************/
typedefvoid(^myBlock)(void);
@interfaceMyObject:NSObject
{
myBlock blk;
}
@end
@implementationMyObject
- (id)init
{
self=[superinit];
blk = ^{
NSLog(@"self = %@",self);
};
returnself;
}
- (void)dealloc
{
NSLog(@"dealloc");
}
@end
/************** main function **************/
int main()
{
id myObject=[[MyObjectalloc] init];
NSLog(@"%@",myObject);
return 0;
}
由于self是__strong修飾,在 ARC 下,當(dāng)編譯器自動(dòng)將代碼中的 block 從??截惖蕉褧r(shí),block 會(huì)強(qiáng)引用和持有self,而self恰好也強(qiáng)引用和持有了 block,就造成了傳說(shuō)中的循環(huán)引用。

由于循環(huán)引用的存在,造成在main()函數(shù)結(jié)束時(shí),內(nèi)存仍然無(wú)法釋放,即內(nèi)存泄露。編譯器也會(huì)給出警告信息
warning: capturing 'self' strongly in this block is likely to lead to a retain cycle [-Warc-retain-cycles]
blk = ^{NSLog(@"self = %@", self);};
note: Block will be retained by an object strongly retained by the captured object
blk = ^{NSLog(@"self = %@", self);};
為了避免這種情況發(fā)生,可以在變量聲明時(shí)用__weak修飾符修飾變量self,讓 block 不強(qiáng)引用self,從而破除循環(huán)。iOS4 和 Snow Leopard 由于對(duì) weak 的支持不夠完全,可以用__unsafe_unretained代替。
- (id)init
{
self = [super init];
id __weak tmp = self;
blk = ^{NSLog(@"self = %@", tmp);};
return self;
}

再看一個(gè)例子:
@interface MyObject : NSObject
{
myBlock blk;
id _obj;
}
@end
@implementation MyObject
- (id)init
{
self = [super init];
blk = ^{ NSLog(@"_obj = %@", _obj); };
return self;
}
...
...
@end
上面的例子中,雖然沒(méi)有直接使用 self,卻也存在循環(huán)引用的問(wèn)題。因?yàn)閷?duì)于編譯器來(lái)說(shuō),_obj就相當(dāng)于self->_obj,所以上面的代碼就會(huì)變成
blk = ^{ NSLog(@"_obj = %@", self->_obj); };