36

我有一个复杂的 iPad 视图,我通过多个视图控制器进行管理。我以前(在 iOS6/Xcode 4.5 之前)通过在代码中分配我的视图控制器来做到这一点,并通过到主视图的链接将各种视图连接到它们。

我想做的是使用新的 UIContainerView 容器视图将视图控制器嵌入情节提要文件中。我似乎无法将 IBOutlet 链接到嵌入式视图控制器到主控制器。

是否有可能做到这一点?或者通过代码中的标签或其他内容检索嵌入式控制器?

这个问题特别是关于使用容器视图

4

5 回答 5

71

在某些情况下,另一种选择是使用-prepareForSegue:sender:.

例如,如果我在 aUINavigationController中嵌入了一个,我可以在情节提要中将CustomContainerViewController嵌入 segue 命名为并在via中捕获它embedContentStackCustomContainerViewController

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"embedContentStack"]) {
        // can't assign the view controller from an embed segue via the storyboard, so capture here
        _contentStack = (UINavigationController *)segue.destinationViewController;
    }
}
于 2012-12-11T19:34:03.217 回答
22

我不确定“检索嵌入式控制器”是什么意思。当您想使用控制器时,您可以使用 UIStoryboard 方法 instantiateViewControllerWithIdentifier:,使用您在 IB 中提供给控制器的标识符。您还可以使用 performSegueWithIdentifier:sender: 方法(它也实例化了视图控制器)。您应该查看 Apple 文档中的“在您的应用程序中使用视图控制器”部分。它还提到了子视图控制器与容器控制器同时实例化的事实。

编辑后:如果您将容器视图嵌入到另一个视图控制器中,则可以使用 self.childViewControllers 从包含控制器中引用该嵌入式视图的控制器(这将是一个数组,因此如果只有一个,您可以使用 lastObject 获取它) .

于 2012-10-01T15:58:53.967 回答
3

这是关于它的另一个线程:Access Container View Controller from Parent iOS

他们建议在prepareForSegue中保留参考或在self.childViewControllers中搜索嵌入的viewController

于 2014-11-04T11:17:50.203 回答
0

注意事项

在继续使用这个问题的答案之前,您可能希望反映嵌入式事物是否真的需要成为视图控制器。

例如,如果您要嵌入一个UICollectionViewController子类,您能否改为嵌入一个UICollectionView子类?或者,更好的是,您可以嵌入一个UIView隐藏UICollectionView在简单 ViewModel 后面的子类吗?

在我目前正在处理的代码库中,我将两个视图控制器嵌入到另一个视图控制器中。两者都可以很容易地成为普通视图,然后可以更容易地绑定到情节提要中,而无需这些杂乱的代码。

不幸的是,它们目前是视图控制器,我现在无法将它们简化为普通视图,因此必须这样做。

背景

我正在使用Playful Geekprepare(for segue:, sender:)建议的方法来获取嵌入 segue 。

我想展示我为此使用的 swift,因为它看起来相当整洁......</p>

class EditionLandingViewController: UIViewController {
    fileprivate var titlesView: SectionTitlesViewController!
    fileprivate var sectionsView: SectionsViewController!
}

//MARK:-

extension EditionLandingViewController {
    private enum SegueId: String {
        case embedTitles
        case embedSections
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        super.prepare(for: segue, sender: sender)

        guard
            let segueRawId = segue.identifier,
            let segueId = SegueId(rawValue: segueRawId)
            else { return }

        switch segueId {
        case .embedTitles:
            self.titlesView = segue.destination as! SectionTitlesViewController

        case .embedSections:
            self.sectionsView = segue.destination as! SectionsViewController
        }
    }
}

讨论

我选择将segues 命名为 action methods

为 segue 标识符使用enumcase 意味着您已经拥有了编译器和工具,因此很难弄错 segue 名称。

在这种情况下,将 segue id 保持在private enum范围extension内似乎是合适的,因为在其他任何地方都不需要这些 segue(perform例如,它们不能被编辑)。

我正在为嵌入式视图控制器使用隐式展开的类型,因为(在我的情况下)如果它们丢失,这是一个逻辑错误。

同样,我也很乐意强制转换目标视图控制器类型。同样,如果这些类型不相同,那将是一个逻辑错误。

于 2018-04-25T07:59:03.507 回答
0

票数最高的答案的Swift版本。多年后,Interface Builder 似乎仍然不支持将 IBOutlets 拖到嵌入式容器视图中。

相反,将网点设置在prepare(for:sender:)

@IBOutlet var someViewController: SomeViewController!

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "EmbedSomeViewController", let destination = segue.destination as? SomeViewController {
        someViewController = destination
    }
}

您还必须在 Storyboard 上设置 UIContainerView。Xcode 会自动生成一个嵌入转场;设置 segue 的Identifier.

在情节提要上设置标识符

于 2021-09-21T01:52:54.503 回答