ios 将子视图控制器添加到当前视图控制器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32964884/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 07:55:13  来源:igfitidea点击:

Add child view controller to current view controller

iosobjective-cuinavigationcontroller

提问by Laur Stefan

I am trying to add a child view controller in code, to the current view controller from storyboard by using the next code:

我正在尝试使用以下代码在代码中将子视图控制器添加到故事板中的当前视图控制器:

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、CGContextRestoreGState

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.

我还阅读了一些帖子,在一些帖子中建议在传递数据之前分配和初始化视图控制器,我也尝试过,但没有任何运气。

采纳答案by kirander

didMoveToParentViewController must be the last.

didMoveToParentViewController 必须是最后一个。

回答by Shahzaib Maqbool

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.

有关更多信息,请查看此链接

回答by Piyush

  • Configuring a Container in Interface Builder.
  • 在 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.

要在设计时创建父子容器关系,请将容器视图对象添加到故事板场景中,如下图所示。容器视图对象是一个占位符对象,表示子视图控制器的内容。使用该视图来调整与容器中其他视图相关的子级根视图的大小和位置。

enter image description here

在此处输入图片说明

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:

要以编程方式将子视图控制器合并到您的内容中,请通过执行以下操作在相关视图控制器之间创建父子关系:

  1. 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.
  2. 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.
  3. Add any constraints for managing the size and position of the child's root view.
  4. Call the didMoveToParentViewController: method of the child view controller.
  1. 调用addChildViewController:容器视图控制器的方法。这个方法告诉 UIKit 你的容器视图控制器现在正在管理子视图控制器的视图。
  2. 将子视图的根视图添加到容器的视图层次结构中。作为此过程的一部分,请始终记住设置孩子框架的大小和位置。
  3. 添加任何约束来管理子视图的大小和位置。
  4. 调用子视图控制器的 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];
}

Swift:

斯威夫特

func displayContentController(_ content: UIViewController?) {
if let content = content {
    addChild(content)
}
content?.view.frame = frameForContentController()
view.addSubview(currentClientView)
content?.didMove(toParent: self)

}

}

More detail explanation of the same example is given at Apple developer programming guide.

Apple 开发人员编程指南中给出了同一示例的更详细说明。

回答by jason z

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".
  • 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).
  • 故事板名称是“主要”。
  • 故事板中的视图控制器标识符名为“LOGIN”。
  • 这使用情节提要来创建加载视图控制器,但同样可以通过编程来完成。在尝试访问视图的框架之前,只需确保视图已加载到内存中,否则您将崩溃(执行诸如模态呈现视图控制器之类的操作)。

回答by atalayasa

You can also create an extension for adding and removing UIViewController.

您还可以创建用于添加和删除UIViewController.

extension UIViewController {
    func addChildViewControllerWithView(_ childViewController: UIViewController, toView view: UIView? = nil) {
        let view: UIView = view ?? self.view
        childViewController.removeFromParent()
        childViewController.willMove(toParent: self)
        addChild(childViewController)
        childViewController.didMove(toParent: self)
        childViewController.view.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(childViewController.view)
        view.addConstraints([
            NSLayoutConstraint(item: childViewController.view!, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: childViewController.view!, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: childViewController.view!, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: childViewController.view!, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0)
        ])
        view.layoutIfNeeded()
    }

    func removeChildViewController(_ childViewController: UIViewController) {
        childViewController.removeFromParent()
        childViewController.willMove(toParent: nil)
        childViewController.removeFromParent()
        childViewController.didMove(toParent: nil)
        childViewController.view.removeFromSuperview()
        view.layoutIfNeeded()
    }
}

Whenever you'd like to add UIViewControllerin the viewDidLoad()method you need to call addChildViewControllerWithView(someVC)

每当您想添加需要调用UIViewControllerviewDidLoad()方法时addChildViewControllerWithView(someVC)