笔记:iOS中addChildViewController的使用

iOS早在iOS5的时候为了解耦、更加清晰的处理页面View的逻辑,UIViewController提供了addChildViewController方法,将ViewController作为容器处理视图控制器的切换,将比较复杂的UI使用子ViewController来管理。

iOS5.0之前只能在ViewControllerview中不断的通过addSubView添加subViewVCview视图层级中。这样使得主ViewController中的内容越来越混乱,代码越来越多,subView的管理越来越困难。
iOS5.0之后按照MVC的原则,每个ViewController只需要管理一个view视图层次结构,因此我们可以使用childViewController来拆分开发中比较复杂的View。并且此时的childViewController拥有了与父ViewController同步的声明周期。

项目中使用:

在我们项目的APP首页的实现中使用到了,首页内容展示位推荐分类菜单,以及每个菜单下的内容展示,不同的分类下的内容view展示的UI多样化。

相关方法:

///子视图控制器数组
@property(nonatomic,readonly) NSArray *childViewControllers

///向父VC中添加子VC
- (void)addChildViewController:(UIViewController *)childController

///将子VC从父VC中移除
- (void) removeFromParentViewController

///fromViewController 当前显示在父视图控制器中的子视图控制器
///toViewController 将要显示的姿势图控制器
///duration 动画时间
/// options 动画效果(渐变,从下往上等等,具体查看API)
///animations 转换过程中得动画
///completion 转换完成
- (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion

///当向父VC添加子VC之后,该方法会自动调用;
- (void)willMoveToParentViewController:(UIViewController *)parent

///从父VC移除子VC之后,该方法会自动调用
- (void)didMoveToParentViewController:(UIViewController *)parent

如何使用?:

  • 如果在view上添加的只是简单的控件的话,那么使用addSubView添加到父ViewController上;
  • 如果子视图是比较复杂的视图集合,功能丰富,就选择使用addChildViewController来添加新的子ViewController,但也需要通过addSubview将子ViewControllerview添加到父视图的视图层级中;
  • iOS5之后使用addChildViewController时的原则,我们在使用addSubview的时候,同时调用addChildViewController方法将subView对应的viewController也加到当前viewController的管理中;
  • 对于那些不需要显示的subView,只需通过addChildViewControllersubVC添加到父控制器中,需要显示时再调用transitionFromViewController方法将其显示出来;
  • 当收到系统的 Memory Warning 的时候,系统也会自动把当前没有显示的 subview 销毁掉 掉,以节省内存;
  • 优点:
  1. 使页面逻辑更加清晰明了,遵循MVC模式,每个View对应相应的ViewController;
  2. 当存在不需显示的view时,将不会被加载,减少内尺使用;
  3. 当收到内存警告时,会将没有加载出的view率先释放,优化了程序的内存释放机制;

系统方法解释:

  • addChildViewController

[A父视图控制器 addChildViewController:B子视图控制器]在视图控制器A中添加了子视图控制器B.调用这个方法时如果子视图控制器已经有父视图控制器了,那么调用该方法会先把子视图控制器从之前的父视图控制器中移除,然后再添加到当前的视图控制器上作为子视图控制器。

注意:调用addChildViewController后会自动调用willMoveToParentViewController:superVC方法;

  • removeFromParentViewController

将子视图控制器从父视图控制器中移除,移除之后将自动调用didMoveToParentViewController

注意:调用removeFromParentViewControlle后会调用didMoveToParentViewController:nil方法

  • willMoveToParentViewController

当一个视图控制器从视图控制器容器中被添加或者被删除之前,该方法被调用parent:父视图控制器,如果没有父视图控制器,将为nil;当调用removeFromParentViewController方法是必须先手动调用该方法,且parent参数为nil。

  • didMoveToParentViewController

当从一个视图控制容器中添加或者移除viewController后,该方法被调用;当调用addChildViewController方法时必须手动调用该方法,且parent参数为父控制器。

代码展示:

  • 添加子VC
//自动调用,可以省略 
//[childVC willMoveToParentViewController: superVC];
[superVC addChildViewController:childVC];
[superVC.view addSubview:childVC.view];
[childVC didMoveToParentViewController:superVC];
  • 删除子VC
[childVC willMoveToParentViewController];
[childVC removeFromParentViewController];
//自动调用,可以省略
//[childVC didMoveToParentViewController:nil]; 
  • 切换子VC
[self addChildViewController:newController];
[self transitionFromViewController:oldController toViewController:newController duration:1.5f options:UIViewAnimationOptionCurveEaseOut animations:^{
        
} completion:^(BOOL finished) {
    if (finished) {
        [newController didMoveToParentViewController:self];
        [oldController willMoveToParentViewController:nil];
        [oldController removeFromParentViewController];
        self.currentVC = newController;
    }
    else{
        self.currentVC = oldController;
    }
}];

总结:

  1. addChildViewController向父视图控制器中添加子视图控制器时,添加之后自动调用willMoveToParentViewController,需要手动调用didMoveToParentViewController
  2. removeFromParentViewController将子视图控制器从父视图控制器中移除,移除之后自动调用didMoveToParentViewController: nil参数为nil,需要在移除前手动调用willMoveToParentViewController
  3. transitionFromViewController:toViewController在调用这个方法之前先调用[fromViewController willMoveToParentViewController:nil]然后在completion后调用[toViewController didMoveToParentViewController:self]方法;
  4. 在切换子视图控制器显示的时候需要保证切换的子视图控制器已经被添加到父视图控制器中;
  5. 当某个子视图控制器将从父视图控制器中删除时,parent参数为nil,即:[将被删除的VC willMoveToParentViewController:nil];
  6. 当某个子试图控制器将加入到父视图控制器时,parent参数为父视图控制器,即:[将被加入的VC didMoveToParentViewController:superVC];

参考文献

  1. https://blog.csdn.net/yongyinmg/article/details/40619727
  2. iOS之ViewController容器篇
  3. 学习笔记:addChildViewController
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容