UIViewController LifeCycle的一些随想

前言 据谣传:iOS为了实现零延迟拍照,从开启VedioSession的时候,就一直在缓存,所以非常占用内存。在小内存的设备上(如iTouch4)会出现释放掉navigation栈内所有页面的情况。这个时候pop回上一个view会发生什么情况呢?

UIViewController LifeCycle

首先得从LifeCycle说起,在UIViewController中,和LifeCycle有关的API有:

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)loadView; // This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly.

- (void)viewWillUnload NS_DEPRECATED_IOS(5_0,6_0);
- (void)viewDidUnload NS_DEPRECATED_IOS(3_0,6_0); // Called after the view controller's view is released and set to nil. For example, a memory warning which causes the view to be purged. Not invoked as a result of -dealloc.

- (void)viewDidLoad; // Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.

- (void)viewWillAppear:(BOOL)animated;    // Called when the view is about to made visible. Default does nothing
- (void)viewDidAppear:(BOOL)animated;     // Called when the view has been fully transitioned onto the screen. Default does nothing
- (void)viewWillDisappear:(BOOL)animated; // Called when the view is dismissed, covered or otherwise hidden. Default does nothing
- (void)viewDidDisappear:(BOOL)animated;  // Called after the view was dismissed, covered or otherwise hidden. Default does nothing

- (void)didReceiveMemoryWarning; // Called when the parent application receives a memory warning. On iOS 6.0 it will no longer clear the view by default.

很多,但从名字上基本上就能看懂。只要注意一点:

这些东西全都是view的状态,和controller没有任何关系。例如当viewDidUnload调用的时候,并不代表者controller会dealloc,只是view被释放了。controller持有着view和model,model的数据依然健在

更多细节可以看这张图:

MEMORY WARNING

对于一般应用,内存不足并不是常见的现象,但正如前言中提到的iTouch4+摄像头这种情况,但会经常出现,那么在先不考虑iOS6的情况下,会发生什么事情呢?

首先,系统发现内存不足,要检查UI的栈内有没有可以释放的东西。

然后,发现上一个页面没有释放,那么释放掉它。然后call didReceiveMemoryWarning –> viewDidUnload

不断循环,释放掉所有无用内存。会不会采用一些LRU之类的算法呢?无从得知。

这时达到了一个关键点:用户取消拍照,popView

当出现了这样的情况,UIViewController 发现,我的view是nil。那么就要按照这个顺序:

  • loadView
  • viewDidLoad
  • viewWillAppear
  • viewDidAppear 完成UI重新加载

Bad Habit

网上很多开发者写的demo都有一个小小的问题,就是把很多成员变量的初始化写在了viewDidLoad里面。

这个在正常情况下不会发生任何问题的。但是,一旦内存不足了,奇怪的事情就都来了。

可以设想这么一个情况,第一个页面是经过用户输入动态数据的tableView,你初始化写在了viewDidLoad里面。然后下一个页面载入了非常多的纹理,导致这个页面的view被释放掉了。

但是用户又pop掉了当前页面,导致重新加载前面的tableview。

这个时候出现了如下几个问题:

  • 初始化对象,重新初始化,导致数据丢失
  • 原来的对象,若没有开启arc的话就没有release,导致程序内存泄露。

Right Way————Lazy Loading

不要觉得麻烦,将所有数据都换成lazy loading 的话,就不会出现那种情况了,毕竟若我第一次分配了内存,我就不会再度给它分配内存了。

什么?你不懂什么是Lazy Loading?

面壁去!不给讲,不懂Lazy Loading 搞什么iOS开发!

Comments