【问题标题】:Add child view controller to UINavigationController将子视图控制器添加到 UINavigationController
【发布时间】:2013-10-15 23:36:43
【问题描述】:

我正在尝试使用以下代码将子视图控制器添加到包含在 UINavigationController 中的 UIViewController

- (void)buttonTapped:(id)sender
{
    MyChildController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MyChild"];
    [self addChildViewController:viewController];
    [self.view addSubview:viewController.view];
    [viewController didMoveToParentViewController:self];


    viewController.view.alpha = 0.0f;
    [UIView animateWithDuration:0.4 animations:^{
        viewController.view.alpha = 1.0f;
    }];
}

但结果是这样的:

如您所见,UINavigatioBarUIToolbar 仍位于子视图控制器的顶部。我怎样才能把子视图控制器放在首位?我已经尝试将代码替换为:

[self.navigationController addChildViewController:viewController];
    [self.navigationController.view addSubview:viewController.view];
    [viewController didMoveToParentViewController:self.navigationController];

但是这样viewControllerviewDidAppear:animated 就不会被调用。我不知道,为什么。

【问题讨论】:

    标签: iphone objective-c uiviewcontroller ios7 childviewcontroller


    【解决方案1】:

    @Pwner的回答 Swift 版:

    将子元素添加到 UINavigaitonController

    let child = MyChildViewController()
    self.navigationController?.addChildViewController(child)
    guard let navigationController = navigationController else {
        return
    }
    child.view.frame = navigationController.view.bounds
    child.beginAppearanceTransition(true, animated: true)
    self.navigationController?.view.addSubview(child.view)
    self.view.alpha = 0
    UIView.animate(withDuration: 0.3, animations: {
        child.view.alpha = 1.0
    }, completion: { _ in
        guard let navigationController = self.navigationController else {
            return
        }
        child.endAppearanceTransition()
        child.didMove(toParentViewController: navigationController)
    })
    

    从 UINavigationController 中移除一个子节点

    child.willMove(toParentViewController: nil)
    child.beginAppearanceTransition(false, animated: true)
    UIView.animate(withDuration: 0.3, animations: {
        child.view.alpha = 0.0
    }, completion: { _ in
        guard let navigationController = self.navigationController else {
            return
        }
        child.view.removeFromSuperview()
        child.endAppearanceTransition()
        child.removeFromParentViewController()
    })
    

    【讨论】:

      【解决方案2】:

      @Sam 的评论是正确的。您需要调用beginApperanceTransition:animated:endAppearanceTransition 以触发viewDidAppearUINavigationController在添加子视图控制器时不调用viewDidAppear的原因是因为它已经覆盖了它的容器组合方法,以防止程序员在奇怪的地方添加子视图控制器。在您的情况下,它不希望您的子视图覆盖导航栏。导航控制器的正确用法是让孩子出现在导航栏下方。尽管如此,您仍然可以通过手动告诉孩子它何时出现以及何时结束来强制使用这种非标准 UI。

      向 UINavigationController 添加一个子节点

      MyChildViewController* child = [[MyChildViewController alloc] init];
      [self.navigationController addChildViewController:child];
      child.view.frame = self.navigationController.view.bounds;
      [self.navigationController.view addSubview:child.view];
      child.view.alpha = 0.0;
      [child beginAppearanceTransition:YES animated:YES];
      [UIView
          animateWithDuration:0.3
          delay:0.0
          options:UIViewAnimationOptionCurveEaseOut
          animations:^(void){
              child.view.alpha = 1.0;
          }
          completion:^(BOOL finished) {
              [child endAppearanceTransition];
              [child didMoveToParentViewController:self.navigationController];
          }
      ];
      

      从 UINavigationController 中移除一个孩子

      [child willMoveToParentViewController:nil];
      [child beginAppearanceTransition:NO animated:YES];
      [UIView
          animateWithDuration:0.3
          delay:0.0
           options:UIViewAnimationOptionCurveEaseOut
          animations:^(void){
              child.view.alpha = 0.0;
          }
          completion:^(BOOL finished) {
              [child endAppearanceTransition];
              [child.view removeFromSuperview];
              [child removeFromParentViewController];
          }
      ];
      

      【讨论】:

      • 我认为孩子在被删除时会打电话给didMoveToParentViewController:。类似[child didMoveToParentViewController:nil]
      • beginAppearanceTransition 应该在addSubview 之前调用,endAppearanceTransition 应该在removeFromSuperview 之后调用,否则可能会出现“不平衡调用”错误。
      【解决方案3】:

      在您的第一个视图控制器中,执行以下操作:

      - (IBAction)buttonClick:(id)sender
      {
          SecondViewController *secondView = [self.storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
          UIImage *blurryImage = [UIImage imageNamed:@"foo.jpeg"];
          secondView.imageView.image = blurryImage;
          [self.navigationController addChildViewController:secondView];
          secondView.view.frame = self.navigationController.view.frame;
          [self.navigationController.view addSubview:secondView.view];
      }
      

      然后在您的第二个视图控制器中,为您的 imageview 添加 getter:

      -(UIImageView *)imageView
      {
          if( _imageView == nil )
          {
              _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 548)];
              [self.view addSubview:_imageView];
          }
          return _imageView;
      }
      

      【讨论】:

      • 我正在尝试使用 viewcontroller-container 方法,因为我需要模糊也是半透明的模态视图控制器的背景视图。效果与从屏幕顶部下拉的通知视图相同。背景是半透明的,它也是模糊/磨砂玻璃。为什么如果我将子视图控制器添加到self.navigationController,则不会调用viewDidAppear 方法?
      • 嗯...不太确定...你试过调用 [viewController viewWillAppear:NO] 吗?
      • 是的,它什么也没做。我需要在[viewController didMoveToParentViewController:self.navigationController] 之后拨打[viewController viewDidAppear:NO]。为什么不调用这些方法?否则,如果我将子视图控制器添加到 self 而不是 self.navigationController 它可以工作,但如上图所示,视图位于 navigationController 的“内部”。
      • 所以我只是编写了一个简单的问题案例,看起来 viewDidLoad 被调用了。为什么不把你的逻辑放在那里?我在想象当它被隐藏时你正在释放你的视图,对吗?
      • 为了调用viewWillAppear:viewDidAppear:,您需要将消息-beginAppearanceTransition:animated: 发送到负责您添加的视图的视图控制器。然后你做动画,如果有的话。并在动画完成块中,将-endAppearanceTransition 发送到出现的视图控制器。注意:不要调用 [viewController viewDidAppear:NO] - 你不应该自己调用这些方法。
      猜你喜欢
      • 2014-05-23
      • 2015-06-24
      • 1970-01-01
      • 2016-01-03
      • 2015-09-04
      • 1970-01-01
      • 1970-01-01
      • 2013-06-05
      • 2023-03-11
      相关资源
      最近更新 更多