addChildViewController

If the new child view controller is already the child of a container view controller, it is removed from that container before being added.
This method is only intended to be called by an implementation of a custom container view controller. If you override this method, you must call super in your implementation.

如果这个子 view controller 已经被添加到了一个容器 controller 当中,那在它被添加进新的容器controller之前会从旧的容器中移除.

这个方法只能被用来实现一个自定义的容器controller添加子controller.如果你重写了这个方法,你必须调用super方法.

使用源码:

AppDelegate.h + AppDelegate.m

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end
#import "AppDelegate.h"
#import "RootViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // 加载根视图控制器
self.window.rootViewController = [RootViewController new]; self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
} @end

RootViewController.h + RootViewController.m

#import <UIKit/UIKit.h>

@interface RootViewController : UIViewController

@end
#import "RootViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h" // 获取当前屏幕尺寸
#define SCR_HEIGHT [UIScreen mainScreen].bounds.size.height // 设置按钮高度
static CGFloat downLenth = .f; // 标示button的枚举值
typedef enum
{ BUTTON_1 = 0x11,
BUTTON_2, } EFlags; @interface RootViewController () { UIViewController *currentVC; } @property (nonatomic, strong) UIView *showArea; // 加载子controller的view
@property (nonatomic, strong) FirstViewController *firstVC; // 子controller
@property (nonatomic, strong) SecondViewController *secondVC; // 子controller @end @implementation RootViewController - (void)viewDidLoad
{
[super viewDidLoad]; // 初始化控制器
[self controllersInit]; // 初始化要展示的区域
[self showAreaInit]; // 初始化按钮
[self buttonsInit];
} #pragma mark - 初始化控制器
- (void)controllersInit
{
// 初始化两个控制器并作为root控制器的subController
_firstVC = [FirstViewController new];
[self addChildViewController:_firstVC];
[_firstVC didMoveToParentViewController:self]; _secondVC = [SecondViewController new];
[self addChildViewController:_secondVC];
[_secondVC didMoveToParentViewController:self];
} #pragma mark - 初始化要展示的区域
- (void)showAreaInit
{
// 初始化要展示的区域
self.showArea = [UIView new];
self.showArea.frame = CGRectMake(, , , SCR_HEIGHT - downLenth - );
self.showArea.layer.masksToBounds = YES;
[self.view addSubview:_showArea]; // 将第一个控制器的view添加进来展示
[self.showArea addSubview:_firstVC.view]; currentVC = _firstVC;
} #pragma mark - 初始化按钮以及按钮事件
- (void)buttonsInit
{
UIButton *firstVCButton = [UIButton new];
[self.view addSubview:firstVCButton];
firstVCButton.backgroundColor = [UIColor redColor];
firstVCButton.tag = BUTTON_1;
firstVCButton.frame = CGRectMake(, SCR_HEIGHT - downLenth, / , downLenth);
[firstVCButton addTarget:self
action:@selector(buttonsEvent:)
forControlEvents:UIControlEventTouchUpInside]; UIButton *secondVCButton = [UIButton new];
[self.view addSubview:secondVCButton];
secondVCButton.backgroundColor = [UIColor yellowColor];
secondVCButton.tag = BUTTON_2;
secondVCButton.frame = CGRectMake( / , SCR_HEIGHT - downLenth, / , downLenth);
[secondVCButton addTarget:self
action:@selector(buttonsEvent:)
forControlEvents:UIControlEventTouchUpInside];
} - (void)buttonsEvent:(UIButton *)button
{
if (button.tag == BUTTON_1)
{
if (currentVC == _firstVC)
{
return;
} [self transitionFromViewController:currentVC
toViewController:_firstVC
duration:
options:UIViewAnimationOptionTransitionNone
animations:^{ }
completion:^(BOOL finished) {
currentVC = _firstVC;
}];
} if (button.tag == BUTTON_2)
{
if (currentVC == _secondVC)
{
return;
} [self transitionFromViewController:currentVC
toViewController:_secondVC
duration:
options:UIViewAnimationOptionTransitionNone
animations:^{ }
completion:^(BOOL finished) {
currentVC = _secondVC;
}];
}
} @end

FirstViewController.h + FirstViewController.m

#import <UIKit/UIKit.h>

@interface FristViewController : UIViewController

@end
#import "FristViewController.h"

@interface FristViewController ()

@end

@implementation FristViewController

- (void)viewDidLoad
{
[super viewDidLoad]; NSLog(@"FirstViewController viewDidLoad");
} - (void)viewWillAppear:(BOOL)animated
{
NSLog(@"FirstViewController viewWillAppear");
} - (void)viewDidAppear:(BOOL)animated
{
NSLog(@"FirstViewController viewDidAppear");
} - (void)viewWillDisappear:(BOOL)animated
{
NSLog(@"FirstViewController viewWillDisappear");
} - (void)viewDidDisappear:(BOOL)animated
{
NSLog(@"FirstViewController viewDidDisappear");
} @end

SecondViewController.h + SecondViewController.m

#import <UIKit/UIKit.h>

@interface SecondViewController : UIViewController

@end
#import "SecondViewController.h"

@interface SecondViewController ()

@end

@implementation SecondViewController

- (void)viewDidLoad
{
[super viewDidLoad]; NSLog(@"SecondViewController viewDidLoad");
} - (void)viewWillAppear:(BOOL)animated
{
NSLog(@"SecondViewController viewWillAppear");
} - (void)viewDidAppear:(BOOL)animated
{
NSLog(@"SecondViewController viewDidAppear");
} - (void)viewWillDisappear:(BOOL)animated
{
NSLog(@"SecondViewController viewWillDisappear");
} - (void)viewDidDisappear:(BOOL)animated
{
NSLog(@"SecondViewController viewDidDisappear");
} @end

需要注意的地方:

1. 容器controller最好定义一个专门用来展示子controller相关view的区域,如例子中的,其中,masksToBounds很重要,要不然,整个controller都会被展示出来的.

self.showArea = [UIView new];
    self.showArea.frame = CGRectMake(0, 0, 320, SCR_HEIGHT - downLenth - 10);
    self.showArea.layer.masksToBounds = YES;
    [self.view addSubview:_showArea];
   
    [self.showArea addSubview:_firstVC.view];

2. 调用完addChildViewController之后还需要调用didMoveToParentViewController,官方文档里面有说明.

3. 为什么在点击一个按钮切换控制器的时候,showArea什么都不用设置,为何还能显示出变化呢?

其实这一点我也没弄明白为何呢.

4. 这个与UITabbarController的功能类似,都有懒加载功能,实际上可以用来当做模拟UITabbarController使用,具备更高自由度的定制Tabbar的功能.

使用addChildViewController手动控制UIViewController的切换的更多相关文章

  1. 使用 Storyboard Segue 实作 UIViewController 的切换

    http://blog.csdn.net/mazhen1986/article/details/7791430 Storyboard 是在 iOS 5 SDK 中才出现的新名词,它其实就是原本的 Xi ...

  2. 【Xamarin 开发 IOS --使用 Storyboard Segue 实作 UIViewController 的切换 (实例)】

    注意:在vs2015中进行画板之间的导航的时候,使用CTRL+鼠标左键进行导航的设定. 使用 NavigationController 进行 画板的链接.... 使用 Storyboard Segue ...

  3. UIVIewController自定义切换效果-b

      之前介绍动画时提过UIView的转场动画,但是开发中我们碰到更多的viewController的切换,ios中常见的viewcontroller切换有四种:模态视图,导航栏控制器,UITabBar ...

  4. 试图切换控制addChildViewController、_transitionFromViewController

    试图切换能够用transitionFromViewController. 步骤: View Controller中能够加入多个sub view,在须要的时候显示出来: 能够通过viewControll ...

  5. 自定义视图控制器切换(iOS)

    在iOS开发过程中,通常我们会使用UINavigationController,UITabbarController等苹果提供的视图控制器来切换我们的视图.在iOS5之前,如果要自定义容器视图控制器很 ...

  6. UIViewController相关知识

    title: UIViewController 相关知识date: 2015-12-13 11:50categories: IOS tags: UIViewController 小小程序猿我的博客:h ...

  7. Swift - UIViewController

    UIViewController类详解: 通过Nib文件初始化 init(nibName nibName: String?, bundle nibBundle: NSBundle?) println( ...

  8. BSBuDeJie_01

    一. 基本配置 1 项目图标 将图片直接拖入Assets-AppIcon 2 启动图片     3 软件名称   4 删除Main.stroryboard   5 设置窗口的根控制器 - (BOOL) ...

  9. UITabBarController底层实现

    1.首先要了解:任何控制器,都能添加子控制器      UIViewController里面有一个方法:     - (void)addChildViewController:(UIViewContr ...

随机推荐

  1. Ansible实战:部署分布式日志系统

    本节内容: 背景 分布式日志系统架构图 创建和使用roles JDK 7 role JDK 8 role Zookeeper role Kafka role Elasticsearch role My ...

  2. CCF CSP 201703-2 学生排队

    博客中的文章均为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201703-2 学生排队 问题描述 体育老师小明要将自己班上的学生按顺序排队.他首先让学生按学号从小到大的顺序排成一排, ...

  3. HBase(一)HBase入门简介

    一 HBase 的起源 HBase 的原型是 Google 的 BigTable 论文,受到了该论文思想的启发,目前作为 Hadoop 的子项目来开发维护,用于支持结构化的数据存储. Apache H ...

  4. CentOS7.5安装MongoDB4.0与CRUD基本操作

    一 MongoDB简介 MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关系数据库和非关系数 ...

  5. loadrunner 脚本中文乱码

    loadrunner 脚本中文乱码 1.新建脚本--->选择协议(Http)-->选项-->高级-->选择“支持字符集”并点选“UTF-8”: 2.在回放脚本之前:Vuser- ...

  6. LeetCode 80. 删除排序数组中的重复项 II

    LeetCode 80. 删除排序数组中的重复项 II

  7. .NET之类型转换

    说起类型转换大家很容易的就会联想到将int类型转换成float类型或者是将double类型转转成int类型之类的转换.当然这可能是大多数人最先接触到的转换方式,也是最简单的转换方式.所谓转换就是从现有 ...

  8. OneDrive开发入门

    OneDrive API提供了对存储在OneDrive上文件的访问能力,大多数API都遵循REST模式,少部分的API可以通过简单的函数来调用 在使用OneDrive API之前要先了解两个简单的概念 ...

  9. 洛谷P1527 [国家集训队] 矩阵乘法 [整体二分,二维树状数组]

    题目传送门 矩阵乘法 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入格式: 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N* ...

  10. python3.6.5中pip3无法使用

    1.在python命令行窗口中: python3 -m ensurepip 创建出pip3.exe.2.再在python3.6的安装目录下的Scripts路径下命令行 pip3 install XXX ...