iOS内存警告didReceiveMemoryWarning

来源:互联网 发布:表示认同的网络用语 编辑:程序博客网 时间:2024/06/05 17:50

iPhone下每个app可用的内存是被限制的,如果一个app使用的内存超过20M,则系统会向该app发送Memory Warning消息。收到此消息后,app必须正确处理,否则可能出错或者出现内存泄露。

     app收到Memory Warning后会调用:UIApplication::didReceiveMemoryWarning -> UIApplicationDelegate::applicationDidReceiveMemoryWarning,然后调用当前所有的viewController进行处理。因此处理的主要工作是在viewController。

    当我们的程序在第一次收到内存不足警告时,应该释放一些不用的资源,以节省部分内存。否则,当内存不足情形依然存在,iOS再次向我们程序发出内存不足的警告时,我们的程序将会被iOS kill掉。



先看看ViewController的生命周期


ViewController的生命周期中各方法执行流程如下: init—>loadView—>viewDidLoad—>viewWillApper—>viewDidApper—>viewWillDisapper—>viewDidDisapper—>viewWillUnload->viewDidUnload—>dealloc

跟随如下文字理解viewController对view加载过程:

1 先判断子类是否重写了loadView,如果有直接调用。之后调viewDidLoad完成View的加载。

2 如果是外部通过调用initWithNibName:bundle指定nib文件名的话,ViewController记载此nib来创建View。

3 如果initWithNibName:bundle的name参数为nil,则ViewController会通过以下两个步骤找到与其关联的nib。

A 如果类名包含Controller,例如ViewController的类名是MyViewController,则查找是否存在MyView.nib;

B 找跟ViewController类名一样的文件,例如MyViewController,则查找是否存在MyViewController.nib。

4 如果子类没有重写的loadView,则ViewController会从StroyBoards中找或者调用其默认的loadView,默认的loadView返回一个空白的UIView对象。

注意第一步,ViewController是判断子类是否重写了loadView,而不是判断调用子类的loadView之后ViewController的View是否为空。就是说,如果子类重写了loadView的话,不管子类在loadView里面能否获取到View,ViewController都会直接调viewDidLoad完成View的加载。


IOS6版本之后修改了ViewController的生命周期,取消了viewDidUnload的调用

从官方文档可以看到:

[plain] view plaincopyprint?
  1. On iOS 6 and Later, a View Controller Unloads Its Own Views When Desired  
  2. The default behavior for a view controller is to load its view hierarchy when the view property is first accessed and thereafter keep it in memory until the view controller is disposed of. The memory used by a view to draw itself onscreen is potentially quite large. However, the system automatically releases these expensive resources when the view is not attached to a window. The remaining memory used by most views is small enough that it is not worth it for the system to automatically purge and recreate the view hierarchy.  

所有的内存管理全交给系统自动完成了。


我们再看看didReceiveMemoryWarning后的流程



On iOS 5 and Earlier

the System May Unload Views When Memory Is Low

跟随以下文字理解卸载过程:

1 系统发出警告或者ViewController本身调用导致didReceiveMemoryWarning被调用

2 调用viewWillUnload之后释放View

3 调用viewDidUnload

On iOS 6 and Later

a View Controller Unloads Its Own Views When Desired

1. 系统不在调用viewDidUnload 

2. 官方提供的窗口刷新的方法

但是当我们app在IOS6以上版本运行时,内存警告后我们怎样管理自己的数据内存呢?

都说是在- (void)didReceiveMemoryWarning;中释放,但释放后怎么再申请回来呢,什么时机做呢?

IOS6之前版本会调用viewDidLoad可写在此函数中,IOS6后怎么解决?

官方给出:

[cpp] view plaincopyprint?
  1. - (void)didReceiveMemoryWarning  
  2. {  
  3.     [super didReceiveMemoryWarning];  
  4.     // Add code to clean up any of your own resources that are no longer necessary.  
  5.     // 通常我们会添加对[self isViewLoaded]的判断,防止多次MemoryWarning导致的self.view=nil时系统自动调用loadView  
  6.     // if ([self isViewLoaded] && !self.view window) 注意顺序,self.view=nil时只要引用self.view系统就会重新加载loadView  
  7.     if ([self.view window] == nil)  
  8.     {  
  9.         // Add code to preserve data stored in the views that might be  
  10.         // needed later.  
  11.    
  12.         // Add code to clean up other strong references to the view in  
  13.         // the view hierarchy.  
  14.         self.view = nil;  
  15.         // 设置此值后,下一次使用view时,会重新加载view,即会重新调用viewDidLoad,这样就解决了自定义控件的刷新时机问题  
  16.     }  
  17. }  



执行self.view = nil; 

在返回界面时系统就会调用viewDidLoad了,具体操作基本和以前相同

[self isViewLoaded]是为了防止self.view为nil时系统自动调用loadView




0 0
原创粉丝点击