【问题标题】:iOS - Programmatically Set A UIContainerView's Embedded UIViewControlleriOS - 以编程方式设置 UIContainerView 的嵌入式 UIViewController
【发布时间】:2015-08-09 02:41:46
【问题描述】:

我有一个UIViewController,里面有一个UIContainerView。根据某个条件是否为真,我想以编程方式将容器视图的嵌入视图设置为不同的UIViewController。我注意到你只能有一个嵌入segue来设置一个UIViewController,那么有没有办法完成这个?

我尝试将容器视图设置为插座,但找不到任何设置嵌入式UIViewController 的方法。任何有关如何开始使用此功能的建议将不胜感激。

【问题讨论】:

  • 你真正想要达到什么目标?
  • 不要混合故事板和程序化设置。一次做一个。将两者混合使用并没有错,但在您完全理解故事板的真正工作原理之前,您可能会感到困惑。
  • 您可能想要覆盖- prepareForSegue:sender: 以根据第三个条件管理不同的转场。或者不要继续,而是以编程方式导航到新的视图控制器,或者使用 - performSegueWithIdentifier:sender: 从情节提要中调用特定的 segue

标签: ios objective-c xcode uiviewcontroller uicontainerview


【解决方案1】:

受 Vive 回答的启发:

extension UIViewController {

    func showContentController(_ controller: UIViewController, containerView: UIView? = nil) {
        controller.willMove(toParentViewController: self)
        self.addChildViewController(controller)
        controller.view.frame = (containerView ?? self.view).frame
        (containerView ?? self.view).addSubview(controller.view)
        controller.view.autoPinEdgesToSuperviewEdges()
        controller.didMove(toParentViewController: self)
    }

    func hideContentController(_ controller: UIViewController) {
        controller.willMove(toParentViewController: nil)
        controller.removeFromParentViewController()
        controller.view.removeFromSuperview()
        controller.didMove(toParentViewController: nil)
    }
}

【讨论】:

  • 这(重复调用will/didMove)不仅不是必需的,还会导致willMovedidMove 被调用两次——这是无效的。请参阅我上面的评论以及来自 Apple 文档的引用。
【解决方案2】:

如果您的意思是交换 UIViewsUIViewController,我认为您的想法是错误的(希望我理解您的概念)。

UIViewController 应该有 1 个设计的 UIView 并且应该管理该视图的值。正如你所说,你可以使用Containers,但是你应该在它的视图中添加UIViewController,所以有一个管理这个视图的实例。你的第一个UIViewController 应该只添加/删除那个ChildViewController

所以我建议:

在 UIViewController 上实现一个类别并添加以下方法:

- (void)displayContentController:(UIViewController *)content {
    [self addChildViewController:content];
    content.view.frame = [[UIScreen mainScreen] bounds];
    [self.view addSubview:content.view];
    [content didMoveToParentViewController:self];
}

- (void)hideContentController:(UIViewController *)content {
    [content willMoveToParentViewController:nil];
    [content.view removeFromSuperview];
    [content removeFromParentViewController];
}

创建AViewControllerBViewController。在AViewController调用(viewDidLoad?):

BViewController *bViewController = [[BViewController alloc] init];
[self displayContentController:bViewController];

BViewController 管理这个控制器的视图。 AViewController 应该只管理何时显示 BViewController 以及何时隐藏它。

如果我误解了你的问题,请发表评论,我会删除这个答案。

【讨论】:

  • 这实际上是一个非常聪明的方法。其他帖子提到了创建自定义容器视图控制器,但这个需要最少的复杂性和思考时间。谢谢! :)
  • 根据文档,willMovedidMove 都应该由您的两种方法调用。
  • @Rivera 来自 Apple 文档:“removeFromParentViewController() 方法在移除子视图控制器后会自动调用子视图控制器的 didMove(toParentViewController:) 方法。” AND “当你的自定义容器调用 addChildViewController(:) 方法时,它会在添加之前自动调用要添加为子视图控制器的 willMove(toParentViewController:) 方法。”_.希望它能解答你的疑惑。
猜你喜欢
  • 2015-11-16
  • 2016-01-01
  • 2017-10-09
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-19
相关资源
最近更新 更多