具有多个嵌入 segues 的 ContainerView

Posted

技术标签:

【中文标题】具有多个嵌入 segues 的 ContainerView【英文标题】:ContainerView with multiple embed segues 【发布时间】:2013-08-23 16:32:48 【问题描述】:

有没有办法让单个 ContainerView 具有多个嵌入 segue?目的是让 ContainerView 根据按下的按钮来保存几个不同的 ViewController;一次只能看到一个。我想使用嵌入 segues,以便在 Interface Builder 中故事板自动显示为与 ContainerView 相同的大小。

我意识到我可以在 InterfaceBuilder 中手动调整其他 ViewController 的大小,但我想要嵌入 segue 提供的自动调整大小。如果有另一种方法可用,那也很好。没有在 viewDidLoad 上加载视图很好 - 如前所述,显示的 ViewController 可以根据按下的按钮而改变。

【问题讨论】:

我意识到这不是您所要求的,但作为另一种解决方法,如何拥有多个 ContainerViews,重叠和相同的大小,每个都有自己的自定义 segue。然后,在代码中,使用 [self performSegueWithIdentifier:] 执行正确的 segue,具体取决于您要显示的子 UIViewController。至少,通过这种方式,您可以保持自动调整大小,保持 IB 中的连接,并保持 prepareForSegue 逻辑。 【参考方案1】:

不,没有办法将多个嵌入 segues 嵌入到一个容器视图中。在 IB 中进行所有设置的一种方法是使嵌入式控制器成为 UITabBarController(隐藏标签栏)。然后,您可以在选项卡中拥有任意数量的控制器,并使用 UITabBarController 的 selectedIndex 属性在代码中切换到它们。

【讨论】:

在问之前我环顾了一圈,但我想我一直希望我错过了什么。哦,好吧,我会忍受视图大小错误的情况。 (你关于使用 TabBarController 的想法很有趣,但不幸的是我的 ContainerView 已经是另一个 TabBarController)。 我意识到这是一个旧答案。我解决这个问题的方法是拥有多个视图容器,并且当时只有一个可见。不知道这是否是最好的方法,但它工作正常。 这绝对是最好的方法,原因有两个,imo:1)在故事板上很容易理解。 2)编码更简单易懂。谢谢rdelmar。这在 Google 搜索中太隐蔽了。 @NunoGonçalves 你到底是怎么做到的?可以帮我吗? @Charmi 这是一年多以前的事了。但我想我添加了 2 个容器,每个容器一个 segue,并根据需要隐藏每个容器。隐藏容器显然会隐藏内容,所以我得到了我想要的行为。【参考方案2】:

是的,我能够在@rdelmar 帖子的启发下实现您正在寻找的东西。您需要做的是将UITabBarViewController 嵌入到您的容器视图中。然后您以编程方式选择您想要呈现的控制器。您可能还想隐藏标签栏。

如果你愿意,你也可以隐藏故事板文件中的标签栏

您可以通过继承 UITabBarController 来选择要呈现的视图控制器:

override func viewDidLoad() 
    super.viewDidLoad()
    self.selectedIndex = 1

您可以通过在viewDidLoad() 中调用self.tabBarController?.tabBar.isHidden = true 来隐藏视图控制器中的标签栏。

【讨论】:

这很有用,但是如何从我的主 VC(包含 ContainerView)中选择一个项目?我尝试将self.tabBarController?.selectedIndex = 5 放入viewDidLoad() 但它不起作用): 你在 'prepareForSegue' 方法中这样做。像这样:'guard let tabBarVC = segue.destination as? UITabBarController else return' 然后是 'tabBarVC.selectedIndex = 5'。也许我在手机上打字时犯了一些错误,但希望这个想法很清楚。 谢谢,兄弟!帮助了我。【参考方案3】:

我知道这个问题有点老了,但我想回答一下,以防你还在寻找或其他人发现这个问题。我遇到了类似的问题,我已经解决了。

简而言之,您将拥有三层: - 一个外部视图控制器(“ExternalViewController”) - 视图控制器管理器(“ViewControllerManager”) - 您真正想要在(“ChildViewController”)之间切换的子视图控制器

在 ExternalViewController 中使用容器视图,并将 segue 嵌入到 ViewControllerManager。 ViewControllerManager 本身将按照in this Apple documentation 的描述以编程方式保存其他 ChildViewController,特别是有关添加和删除子项的部分。

当您添加子视图控制器时,将其框架设置为与 ViewControllerManager 的框架相同(因为您是在 ViewControllerManager 中执行此操作,所以将子视图控制器的框架设置为等于 self.view.frame)。当然,您还需要一些逻辑和外部控件来在 ExternalViewController 内部进行切换。

希望这会有所帮助!

【讨论】:

【参考方案4】:

我发现这篇精彩的文章准确地解释了如何做到这一点:http://sandmoose.com/post/35714028270/storyboards-with-custom-container-view-controllers

你得到你的容器并且可以在后面调用任何视图控制器,有一些设置可以将所有东西链接起来,但是一旦完成,你就会得到一个仍然可用的故事板。

【讨论】:

这个答案是的,根据链接是可能的 这对我来说效果更好。选项卡视图控制器的主要缺点是每个选项卡的 VC 在不可见时继续存在。当它们不可见时,我希望它取消初始化,然后在需要返回时从头开始重新初始化。 链接已售罄 :( 我在this link使用回路机找到了上面的链接内容。这是一个了不起的解决方案,作者将代码发布在 github project 中,该地址仍然有效。【参考方案5】:

我通过使用-shouldPerformSegueWithIdentifier:sender: 实现了这一点。我有一个容器,它传递了一个对象,并根据该对象的类型决定要显示哪个子视图控制器。

结构似乎有点过于复杂,但允许基本视图控制器忽略我拥有的不同类型的任务,将其留给容器视图控制器。 容器视图控制器具有多个容器视图,这些视图仅根据任务类型执行。

我不知道您是否可以通过调用 -performSegueWithIdentifier:sender: 手动执行嵌入转场,但这也可能是一种可能性。

【讨论】:

【参考方案6】:

我也为此苦苦挣扎了很长时间。我有一个不同但相似的嵌入式表格视图控制器,我想根据在视图控制器中设置的参数来显示它们。有效的是在视图控制器中放入带有 IBOutlet 的嵌入式容器。容器可以在 IB 中设置大小限制。但是,不要在 IB 中进行任何嵌入 segue。然后在 viewDidLoad 中,我以编程方式添加正确的视图控制器并将其边缘固定到嵌入容器。

这种方法的核心体现在以下代码(Swift 4)中:

extension UIView 
    func pinToParent() 
        self.translatesAutoresizingMaskIntoConstraints = false
        let attributes: [NSLayoutAttribute] = [.top, .bottom, .right, .left]
        NSLayoutConstraint.activate(attributes.map 
            NSLayoutConstraint(item: self, attribute: $0, relatedBy: .equal, toItem: self.superview, attribute: $0, multiplier: 1, constant: 0)
        )
    


class ColorVC: UIViewController 

    @IBOutlet weak var tableContainer: UIView!
    var color : rgb = .red

    fileprivate var colorTableVC : ColorTableVC?

    override func viewDidLoad() 
        super.viewDidLoad()

        switch color 
        case .red:
            colorTableVC = RedTableVC.init(style: .plain)
        case .green:
            colorTableVC = GreenTableVC.init(style: .plain)
        case .blue:
            colorTableVC = BlueTableVC.init(style: .plain)
        
        if let vc = colorTableVC 
            if (vc.view) != nil 
                self.addChildViewController(vc)
                tableContainer.addSubview(vc.view)
                vc.view.pinToParent()
                vc.didMove(toParentViewController: self)
            
        
    

在 ColorVC 中,可以看到容器 IBOutlet 和主表视图控制器设置的“颜色”参数。 RedTableVC、GreenTableVC 和 BlueTableVC 都是 ColorTableVC 的子类,ColorTableVC 是 UITableViewController 的子类。共同的遗产让我使用一个“colorTableVC”变量来指向任何实例化的控制器。 (并非完全必要)。但这确实避免了复制下面的代码以在层次结构中添加视图并将新控制器固定到容器视图。在顶部,我在 UIView 上做了一个扩展,以将视图固定到其父边缘。

下图显示了如何在 IB 中设置项目,尤其是右侧的视图控制器。在本例中,我将“嵌入式”控制器的高度设置为主视图控制器高度的一半——因此当您旋转设备时,可以看到确实应用了 IB 中设置的约束。

【讨论】:

【参考方案7】:

在您的工作 viewController 中拖动一个 uiview 并将约束设置为顶部、前导、尾随、底部到安全区域(Iphone X 系列)。

现在将容器视图(内容视图)放入该 UIView 中。 将任意数量的内容视图放入该 UIView 并嵌入到相应的 ViewContrllers。

为我工作。

【讨论】:

以上是关于具有多个嵌入 segues 的 ContainerView的主要内容,如果未能解决你的问题,请参考以下文章

在 UITableView 中嵌入的自定义 UICollectionView 中执行 Segue

无法更改为具有多个 segue 的另一个视图控制器。我该如何解决?

在 UITableView 上执行具有多个状态的 segue 的问题

嵌入 Segue 目标视图控制器被排除在 UI 状态恢复之外

嵌入 Segue - iOS 5

程序化嵌入 segue