如何在父视图上添加子视图控制器的视图

7
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    ChildViewController *childviewcontroller = [[ChildViewController alloc] initWithNibName:@"ChildViewController" bundle:nil];


    [self addChildViewController:childviewcontroller];
    [self.view addSubview:childviewcontroller.view];
    [childviewcontroller willMoveToParentViewController:self];
    UIView *cview = [[UIView alloc] init];
    cview = childviewcontroller.view;
    [self.view removeConstraints:self.view.constraints];

    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(cview);
    [self.view addConstraints:[NSLayoutConstraint 
                                constraintsWithVisualFormat:@"H:|-[cview]-|" 
                                                    options:0 metrics:nil                                        
                                                    views:viewsDictionary]];

}

我希望在父视图上添加子视图控制器视图。 添加后,我设置了约束,但对我没有起作用。

我也收到了这样的警告

2013-07-25 10:47:30.564 neenah[1105:c07] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: (1) look at each constraint and try to figure out which you don't expect; 
    (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't 
    understand, refer to the documentation for the UIView 
    property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x9256c90 H:|-(NSSpace(20))-[UIView:0x9256a00]   (Names: '|':UIView:0x92557a0 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x755d690 h=--& v=--& H:[UIView:0x9256a00(320)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x755d5a0 h=--& v=--& UIView:0x9256a00.midX == + 160>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x9256c90 H:|-(NSSpace(20))-[UIView:0x9256a00]   (Names: '|':UIView:0x92557a0 )>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2013-07-25 10:47:30.567 neenah[1105:c07] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x9256bb0 H:[UIView:0x9256a00]-(NSSpace(20))-|   (Names: '|':UIView:0x92557a0 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x7561690 h=--- v=--- H:[UIWindow:0x92527c0(320)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x755fe50 h=-&- v=-&- UIView:0x92557a0.width == UIWindow:0x92527c0.width>",
    "<NSAutoresizingMaskLayoutConstraint:0x755d690 h=--& v=--& H:[UIView:0x9256a00(320)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x755d5a0 h=--& v=--& UIView:0x9256a00.midX == + 160>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x9256bb0 H:[UIView:0x9256a00]-(NSSpace(20))-|   (Names: '|':UIView:0x92557a0 )>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

你只需要加上这一行代码 [self.view addSubview:childviewcontroller.view]; - Puneet Sharma
addChildViewController在iOS5中用于viewController的包含,这将使您轻松创建自己的NavigationCotrollers或TabControllers,它仅在iOS5中可用。您需要这样的东西吗?如果不需要,请删除此行。 - Puneet Sharma
我需要删除哪一行 @Puneet - Dhiyanes KaeYes
@Puneet 不,由于他正在将子视图控制器的视图作为当前控制器视图的子视图添加视图,因此他_绝对应该保留_“addChildViewController”和“didMoveToParentViewController”调用的自定义容器调用。 如果他要支持iOS 5.0之前的版本,那么可以放心,在运行iOS 5(及更高版本)时才进行方法调用的运行时检查。但显然,他正在使用自动布局,这是iOS 6及以上版本的功能,因此他应该进行容器调用。 - Rob
是的,Rob,你说得完全正确。我的错,我有点混淆了。谢谢你的解释。 - Puneet Sharma
显示剩余2条评论
1个回答

13

几点观察:

  1. 您应该关闭 translatesAutoresizingMaskIntoConstraints

    childviewcontroller.view.translatesAutoresizingMaskIntoConstraints = NO;
    
  2. 你应该也定义垂直方向的约束:

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[cview]-|" 
                                                                      options:0
                                                                      metrics:nil                                        
                                                                        views:viewsDictionary]];
    
  3. 与你的问题无关,你不需要为创建[[UIView alloc] init]。你立刻就将它丢弃了。

  4. 我不确定为什么要删除self.view的约束条件。(我猜想你这样做是因为在测试过程中感到很头疼。)你不必这样做。但如果你在这里有其他事情让你认为你需要这样做,请告诉我们是什么。

  5. 当添加一个子控制器时,应该调用didMoveToParentViewController而不是willMoveToParentViewControlleraddChildViewController会自动调用willMoveToParentViewController,你只需要使用didMove...这个方法即可。

因此:

- (void)viewDidLoad {
    [super viewDidLoad];

    // instantiate the view controller

    ChildViewController *childViewController = [[ChildViewController alloc] initWithNibName:@"ChildViewController" bundle:nil];

    // or you can instantiate using storyboard
    //
    // ChildViewController *child = [self.storyboard instantiateViewControllerWithIdentifier:@"ChildIdentifier"];

    // now do the view controller containment calls to update the view controller hierarchy and add the view as appropriate

    [self addChildViewController:childViewController];
    childViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:childViewController.view];
    [childViewController didMoveToParentViewController:self];
    UIView *childView = childViewController.view;

    NSDictionary *views = NSDictionaryOfVariableBindings(childView);
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[childView]-|" options:0 metrics:nil views:views]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[childView]-|" options:0 metrics:nil views:views]];
}

1
感谢您的回复,现在我正在学习这些概念,所以遇到了麻烦。@Rob - Dhiyanes KaeYes
当我使用nib文件加载视图控制器时,这对我很有效。但是,当它来自storyboard时,instantiateViewControllerWithIdentifier就不起作用了。子容器既没有响应约束,也没有响应父视图! - hasan
@hasan83 - 当您使用instantiateViewControllerWithIdentifier时,流程是相同的。我刚测试了一下,它可以正常工作。我敢打赌您可能有一些没有正确定义的约束条件。如果您仍然找不到问题的来源,请发布您自己的问题,并提供一个可重现的示例来描述问题。 - Rob
由于这是我有不同的限制,我注意到Storyboard中的子控制器采用设备屏幕大小并拒绝应用约束! - hasan
我使用了一个nib文件,它起作用了,谢谢你的答案。但是我还不知道故事板控制器的解决方案。 - hasan
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接