在iOS4和iOS5系统中,当内存不足,应用受到MemoryWarning时,系统就会自动调用当前没有在界面上得ViewController的viewDidUnload方法。通常情况下,未显示在界面的ViewController是UINavigationController Push栈中未在栈顶的ViewController,以及UITabBarController中未显示的子ViewController。这些ViewController都在MemoryWarning事件发生时,让系统自动调用viewDidUnload 方法。
在iOS6中,由于viewDidUnload 事件任何情况下都不会被触发,所以苹果在文档中建议,应该将回收内存的相关操作移到另一个函数didReceiveMemoryWarning中。但是如果仅仅写成:(以下为错误示例)
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if(self.isViewLoaded&&!self.view.window)
{
self.view=nil;
}
}
在iOS6以后,不建议将view置为nil的原因如下:
1,UIView有一个CALayer成员变量,CALayer用于将自己画到屏幕上,如下图:
2,CALayer是一个bitmap图像的容器类,当UIView调用自身的drawRect时,CALayer才会创建bitmap图像类。
3,具体占内存的其实是一个bitmap图像类,CALayer只占48Bytes,UiView只占96Bytes。而一个iPad的全屏UIView的bitmap类会占到12MB的大小。
4,在iOS6,当系统发出MemoryWarning时,系统会自动回收bitmap类,但是不回收UIView和CALayer类。这样既能回收大部分内存,又能在需要bitmap类时,通过调用UIView的drawRect:方法重建。
内存优化:
苹果系统对上面的内存回收做了一个优化:
1,当一段内存被分配时,它会被标记成“In User”,以防止被重复使用。当内存被释放时,这段内存被标记为“Not in use”,这样有新的内存申请时,这块内存就可能被分配给其他变量。
2,CALayer包括的具体的bitmap内容的私有成员变量类型为CABackingStore,当收到MemoryWarning时,CABackingStore类型的内存会被标记为Volatile类型,表示这块内存可能再次被原变量使用。
这样,有了上面优化后,当收到MemoryWarning时,虽然所有的CALayer所包含的bitmap内存被标记成volatile了,但是只要这块内存没有被复用,当需要重建bitmap内存时,可以直接被复用,避免了再次调用UIView的drawRect:方法。
简单说:对于iOS6,不需要做任何以前viewDidUnload的事情,更不需要把以前viewDidUnload的代码移到didReceiveMemoryWarning方法中。