I am trying to add a child view controller in code, to the current view controller from storyboard by using the next code:
我正在尝试在代码中添加一个子视图控制器,通过使用下一个代码从storyboard添加到当前视图控制器:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];
LogInTutorialViewController *lvc = [[LogInTutorialViewController alloc] init];
lvc = (LogInTutorialViewController *)[storyboard instantiateViewControllerWithIdentifier:@"LogInTutorialViewControllerID"];
[self displayContentController:lvc];
- (void) displayContentController: (LogInTutorialViewController*) content;
{
//add as childViewController
[self addChildViewController:content];
[content didMoveToParentViewController:self];
[content.view setFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
[self.view addSubview:content.view];
}
The view seem to be displaying on the simulator at least but in console I get a lot or error:
视图似乎至少显示在模拟器上,但在控制台我得到了很多或错误:
<Error>: CGContextSaveGState: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.
And also the same description but different error:
描述相同,但误差不同
CGContextSetLineWidth, CGContextSetLineJoin, CGContextSetLineCap, CGContextSetMiterLimit, CGContextSetFlatness, CGContextAddPath, CGContextDrawPath, CGContextRestoreGState
CGContextSetLineWidth, CGContextSetLineJoin, CGContextSetLineCap, CGContextSetMiterLimit, CGContextSetFlatness, CGContextAddPath, CGContextDrawPath, cgcontext trestoregstate
all these error get logged twice.
所有这些错误都会被记录两次。
Does anyone know what I am doing wrong?
有人知道我做错了什么吗?
also I read a few posts and in some it was suggested to alloc and init the view controller before passing the data, I also tried that without any luck.
我也读了一些文章,在一些文章中建议在传递数据之前分配和初始化视图控制器,我也尝试了一下。
4 个解决方案
#1
4
didMoveToParentViewController must be the last.
didMoveToParentViewController必须是最后一个。
#2
21
why you do not try this code for adding view i think this one is simple and easy..
为什么不试试这段代码添加视图呢?我觉得这段很简单。
self.loginView = [self.storyboard instantiateViewControllerWithIdentifier:@"LOGIN"];
[self addChildViewController:self.loginView];
[self.loginView.view setFrame:CGRectMake(0.0f, 0.0f, self.contentView.frame.size.width, self.contentView.frame.size.height)];
[self.contentView addSubview:self.loginView.view];
[self.loginView didMoveToParentViewController:self];
for further more information check this link.
欲了解更多信息,请查看此链接。
#3
18
- Configuring a Container in Interface Builder.
- 在接口构建器中配置容器。
To create a parent-child container relationship at design time, add a container view object to your storyboard scene, as shown in image below. A container view object is a placeholder object that represents the contents of a child view controller. Use that view to size and position the child’s root view in relation to the other views in the container.
要在设计时创建父子容器关系,请将容器视图对象添加到故事板场景中,如下图所示。容器视图对象是表示子视图控制器内容的占位符对象。使用该视图来调整子视图的大小,并将其与容器中的其他视图相关联。
When you load a view controller with one or more container views, Interface Builder also loads the child view controllers associated with those views. The children must be instantiated at the same time as the parent so that the appropriate parent-child relationships can be created.
当您加载带有一个或多个容器视图的视图控制器时,Interface Builder也会加载与这些视图关联的子视图控制器。子节点必须与父节点同时实例化,以便创建适当的父节点-子节点关系。
If you do not use Interface Builder to set up your parent-child container relationships, you must create those relationships programmatically by adding each child to the container view controller, as described in Adding a Child View Controller to Your Content.
如果不使用Interface Builder来设置父-子容器关系,则必须通过编程方式将每个子元素添加到容器视图控制器中,就像在内容中添加子视图控制器中描述的那样。
- Adding a Child View Controller to Your Content.
- 向内容添加子视图控制器。
To incorporate a child view controller into your content programmatically, create a parent-child relationship between the relevant view controllers by doing the following:
要以编程方式将子视图控制器合并到内容中,请在相关视图控制器之间创建父子关系,方法如下:
- Call the
addChildViewController:
method of your container view controller. This method tells UIKit that your container view controller is now managing the view of the child view controller. - 调用addChildViewController:容器视图控制器的方法。这个方法告诉UIKit你的容器视图控制器现在正在管理子视图控制器的视图。
- Add the child’s root view to your container’s view hierarchy. Always remember to set the size and position of the child’s frame as part of this process.
- 将子视图添加到容器的视图层次结构中。一定要记住在这个过程中设置子框架的大小和位置。
- Add any constraints for managing the size and position of the child’s root view.
- 为管理子根视图的大小和位置添加任何约束。
- Call the didMoveToParentViewController: method of the child view controller.
- 调用didMoveToParentViewController:子视图控制器的方法。
Here is the code for that.
这是它的代码。
- (void)displayContentController:(UIViewController *)content {
[self addChildViewController:content];
content.view.frame = [self frameForContentController];
[self.view addSubview:self.currentClientView];
[content didMoveToParentViewController:self];
}
More detail explanation of the same example is given at Apple developer programming guide.
在Apple developer编程指南中给出了对同一示例的更详细的解释。
#4
3
Solution in Swift (Swift 4 at the time of this writing):
Swift格式的解决方案(本文撰写时Swift 4):
//load the view controller and add as child
storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
loginVC = storyboard.instantiateViewController(withIdentifier: "LOGIN")
addChildViewController(loginVC)
//make sure that the child view controller's view is the right size
loginVC.view.frame = contentView.bounds
contentView.addSubview(loginVC.view)
//you must call this at the end per Apple's documentation
loginVC.didMove(toParentViewController: self)
Notes:
注:
- Storyboard name is "Main".
- 故事板的名字是“主要”。
- View controller identifier in the storyboard is named "LOGIN".
- 故事板中的视图控制器标识符被命名为“LOGIN”。
- This uses a storyboard to create load the view controller, but the same can be done programmatically. Just make sure the view is loaded into memory before you try and access the view's frame or you will get a crash (do something like present the view controller modally).
- 这使用一个故事板来创建加载视图控制器,但是同样的事情可以通过编程来完成。在尝试访问视图的框架之前,请确保将视图加载到内存中,否则会出现崩溃(做一些类似于以模式显示视图控制器的操作)。
#1
4
didMoveToParentViewController must be the last.
didMoveToParentViewController必须是最后一个。
#2
21
why you do not try this code for adding view i think this one is simple and easy..
为什么不试试这段代码添加视图呢?我觉得这段很简单。
self.loginView = [self.storyboard instantiateViewControllerWithIdentifier:@"LOGIN"];
[self addChildViewController:self.loginView];
[self.loginView.view setFrame:CGRectMake(0.0f, 0.0f, self.contentView.frame.size.width, self.contentView.frame.size.height)];
[self.contentView addSubview:self.loginView.view];
[self.loginView didMoveToParentViewController:self];
for further more information check this link.
欲了解更多信息,请查看此链接。
#3
18
- Configuring a Container in Interface Builder.
- 在接口构建器中配置容器。
To create a parent-child container relationship at design time, add a container view object to your storyboard scene, as shown in image below. A container view object is a placeholder object that represents the contents of a child view controller. Use that view to size and position the child’s root view in relation to the other views in the container.
要在设计时创建父子容器关系,请将容器视图对象添加到故事板场景中,如下图所示。容器视图对象是表示子视图控制器内容的占位符对象。使用该视图来调整子视图的大小,并将其与容器中的其他视图相关联。
When you load a view controller with one or more container views, Interface Builder also loads the child view controllers associated with those views. The children must be instantiated at the same time as the parent so that the appropriate parent-child relationships can be created.
当您加载带有一个或多个容器视图的视图控制器时,Interface Builder也会加载与这些视图关联的子视图控制器。子节点必须与父节点同时实例化,以便创建适当的父节点-子节点关系。
If you do not use Interface Builder to set up your parent-child container relationships, you must create those relationships programmatically by adding each child to the container view controller, as described in Adding a Child View Controller to Your Content.
如果不使用Interface Builder来设置父-子容器关系,则必须通过编程方式将每个子元素添加到容器视图控制器中,就像在内容中添加子视图控制器中描述的那样。
- Adding a Child View Controller to Your Content.
- 向内容添加子视图控制器。
To incorporate a child view controller into your content programmatically, create a parent-child relationship between the relevant view controllers by doing the following:
要以编程方式将子视图控制器合并到内容中,请在相关视图控制器之间创建父子关系,方法如下:
- Call the
addChildViewController:
method of your container view controller. This method tells UIKit that your container view controller is now managing the view of the child view controller. - 调用addChildViewController:容器视图控制器的方法。这个方法告诉UIKit你的容器视图控制器现在正在管理子视图控制器的视图。
- Add the child’s root view to your container’s view hierarchy. Always remember to set the size and position of the child’s frame as part of this process.
- 将子视图添加到容器的视图层次结构中。一定要记住在这个过程中设置子框架的大小和位置。
- Add any constraints for managing the size and position of the child’s root view.
- 为管理子根视图的大小和位置添加任何约束。
- Call the didMoveToParentViewController: method of the child view controller.
- 调用didMoveToParentViewController:子视图控制器的方法。
Here is the code for that.
这是它的代码。
- (void)displayContentController:(UIViewController *)content {
[self addChildViewController:content];
content.view.frame = [self frameForContentController];
[self.view addSubview:self.currentClientView];
[content didMoveToParentViewController:self];
}
More detail explanation of the same example is given at Apple developer programming guide.
在Apple developer编程指南中给出了对同一示例的更详细的解释。
#4
3
Solution in Swift (Swift 4 at the time of this writing):
Swift格式的解决方案(本文撰写时Swift 4):
//load the view controller and add as child
storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
loginVC = storyboard.instantiateViewController(withIdentifier: "LOGIN")
addChildViewController(loginVC)
//make sure that the child view controller's view is the right size
loginVC.view.frame = contentView.bounds
contentView.addSubview(loginVC.view)
//you must call this at the end per Apple's documentation
loginVC.didMove(toParentViewController: self)
Notes:
注:
- Storyboard name is "Main".
- 故事板的名字是“主要”。
- View controller identifier in the storyboard is named "LOGIN".
- 故事板中的视图控制器标识符被命名为“LOGIN”。
- This uses a storyboard to create load the view controller, but the same can be done programmatically. Just make sure the view is loaded into memory before you try and access the view's frame or you will get a crash (do something like present the view controller modally).
- 这使用一个故事板来创建加载视图控制器,但是同样的事情可以通过编程来完成。在尝试访问视图的框架之前,请确保将视图加载到内存中,否则会出现崩溃(做一些类似于以模式显示视图控制器的操作)。