Oh!Coder

Coding Life

iOS6中发生内存警告时的资源释放

| Comments

今天用模拟器进行模拟内存不足的时候,发现系统不再调用viewDidUnload,上网查过之后,发现原因,在此做一记录。

在iOS6之前,如果系统内存不够用,会发出内存警告,并且系统会自动调用UIViewController类型的viewDidUnload方法,你可以把当前屏幕上未显示的相关资源在此方法中进行手动释放掉。例如(ARC环境),

1
2
3
4
5
-(void)viewDidUnload{
    [super viewDidUnload];
    self.view = nil;        //释放view 
    ...                     //释放其它资源
}

但是在iOS6中,由于系统内存不足发出警告时,系统不再调用此方法,而是只调用didReceiveMemoryWarning方法,所以这就需要我们额外做一些判断,然后再释放资源。例如(ARC环境),

1
2
3
4
5
6
7
8
9
10
-(void)exampleUnload{
    [self setView:nil];     //释放view
    ...                     //释放其它资源
}

-(void)didReceiveMemoryWarning{
    if([[self view]window == nil] && [self isViewLoaded]){
        [self exampleUnload];
    }
}

这里有两点我觉得需要注意的地方。

第一点是,虽然一般情况下只释放view对象。但是,我觉得,如果可能的话,还是试着把view上的其它视图也进行手动释放,例如view上如果有一个UIButton对象,名为btn,此时指向btn的除了view以外,还有UIViewController对象,尤其是用Interface Builder创建的视图。因此即便对view进行了释放,btn的计数也进行了减一,但并没有减到零。虽然系统再次调用viewDidLoad方法的时候,会创建新的btn,而旧的btn计数也会减为零,被系统收回,但是如果资源很大的话,而此时view又迟迟不再次进行显示,那么原来的btn就会一直停留在内存中,直到创建新的view为止。

第二点比较明显,就是不要在初始化方法中添加对view进行操作的代码。因为当内存发生警告,对view进行释放之后。再次创建view的时候,并不会再次调用任何初始化方法,而第一次在初始化方法中对view进行操作的代码也不会再次执行,这会造成此时view显示的状态和第一打开软件的时候不一致。

Comments