addChildViewController: VS addSubview:

来源:互联网 发布:广西老年大学网络报名 编辑:程序博客网 时间:2024/06/06 07:48

前言

最近看大神们的博客时,发现一个之前一直没注意到的API:addChildViewController:很有用武之地,很大程度上弥补了经验不深的开发者(ps:说得好像不是我一样!)常使用的addSubview:的不足,而且Apple官方也希望我们在使用[self.view addSubview:XX]的同时调用[self addChildViewController:XX]。
addChildViewController:是从iOS5开始引入的,那为什么Apple要做出这个改变,下面我们就addSubview:单独使用与联合addChildViewController:使用比较一番!


权衡利弊

在某些场景中,UIViewController的view上包含许多的subview,而这其中的view有些是在特定的状态下才会显示(比如:登录、注册和订单的提示信息),对于经验比较浅我们通常就是在viewDidLoad中通过[self.view addSubview:XX]方法将subview加入控制器的view,而对于当前不需要显示的subview就将它隐藏起来。

乍一看好像没什么问题,效果也和预期的一样,而在收到内存警告时我们就只能手动的将subview从superView中移除(想想怎么移除?),同时你还得仔细想想怎样的移除顺序才能保证App的功能受影响程度最小,即使当前没有显示的view其实也存在于内存中,如果此次的操作view始终不会出现,那就白白浪费了内存。每个App的内存都有个阀值,当超过这个值时,系统将关闭App,所以在收到内存警告时,要尽可能多的释放不必要的内存。

在iOS6后,Apple就不建议将view置为nil。UIView有一个CALayer的成员变量,CALayer的作用具体用于将自己画到屏幕上。而CALayer是一个bitmap(位图)图像的容器类,当UIView调用自身的drawRect:时,CALayer才会创建这个bitmap图像类。实际上占内存的其实就是一个bitmap图像类,CALayer占48B,UIView占96B,全屏的ipadUIView的bitmap类会占12MB!iOS6后,当系统发出MemoryWarning时,系统会自动回收bitmap类,不会收UIView和CALayer类,这样就能保证回收大部分内存后,又能在需要bitmap类时,只通过调用UiView的drawRect:方法重建,所以当你想在内存警告时移除暂时不需要的view时还一时间想不到好的法子,可以参考这个:

  • 不要把subview当成成员变量来持有,使用tag来操作;
  • 不要使用viewDidUnload方法(iOS6 deprecated),由系统来控制内存的释放;
  • 在需要的时候实现didReceiveMemoryWarning来释放一些业务数据减少内存的占用,不要操作UIView。

所以单纯的使用addSubview:添加很多subview后内存管理将是个头疼的事,addChildViewController:的引入不但解决了这个问题,还能有别的惊喜!相关的API如下:

// 方法addChildViewController:removeFromParentViewController:transitionFromViewController:toViewController:duration:options:animations:completion:willMoveToParentViewController:didMoveToParentViewController:// 属性@property(nonatomic,readonly) NSArray *childViewControllers

对于当前需要显示的view,我们只需要将对应的控制器通过addChildViewController:加在主控制器的管理队列中,再调用transitionFromViewController:toViewController:duration:options:animations:completion:还能实现多个subview之间的动画跳转,不需要时移除就可以了。(API参上)当收到内存警告时,系统就会自动将当前还没显示的subview从内存中移除,所以我们在需要向主视图中添加subview时就可以临时的创建相应的控制器的局部对象,而非在主控制器类中添加subview的成员变量来控制它的生命周期。很明显联合使用这两个方法有如下好处:

  • 多个控制器视图之间可以实现动画跳转;
  • 页面逻辑更加清晰,降低了代码的耦合度,页面即控制器;
  • 当收到内存警告时,当前不是激活状态下的控制器所占用的内存就会被系统自动释放,十分方便。

总结

对于自始至终都在view上的subview使用addSubview:就足够了,二者的联合使用的应用场景主要是需要进行动态变化的大的subview(比如网易新闻App主界面,这里有个小的demo,有兴趣的可以看一看),当然尽可能多的使用addChildViewController:也不会有什么问题,毕竟官方这是这么希望的!

(ps:笔者自学iOS开发刚近一年,之前没有任何的OOP的经验,写博客旨在分享所学到的一些东西,文笔驽钝,望请见谅!如果博文有什么问题,希望各位同行不吝指出,愿阅读愉快!)

0 0