我有一个复杂的 iPad 视图,我通过多个视图控制器进行管理。我以前(在 iOS6/Xcode 4.5 之前)通过在代码中分配我的视图控制器来做到这一点,并通过到主视图的链接将各种视图连接到它们。
我想做的是使用新的 UIContainerView 容器视图将视图控制器嵌入情节提要文件中。我似乎无法将 IBOutlet 链接到嵌入式视图控制器到主控制器。
是否有可能做到这一点?或者通过代码中的标签或其他内容检索嵌入式控制器?
这个问题特别是关于使用容器视图
我有一个复杂的 iPad 视图,我通过多个视图控制器进行管理。我以前(在 iOS6/Xcode 4.5 之前)通过在代码中分配我的视图控制器来做到这一点,并通过到主视图的链接将各种视图连接到它们。
我想做的是使用新的 UIContainerView 容器视图将视图控制器嵌入情节提要文件中。我似乎无法将 IBOutlet 链接到嵌入式视图控制器到主控制器。
是否有可能做到这一点?或者通过代码中的标签或其他内容检索嵌入式控制器?
这个问题特别是关于使用容器视图
在某些情况下,另一种选择是使用-prepareForSegue:sender:
.
例如,如果我在 aUINavigationController
中嵌入了一个,我可以在情节提要中将CustomContainerViewController
嵌入 segue 命名为并在via中捕获它embedContentStack
CustomContainerViewController
- (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;
}
}
我不确定“检索嵌入式控制器”是什么意思。当您想使用控制器时,您可以使用 UIStoryboard 方法 instantiateViewControllerWithIdentifier:,使用您在 IB 中提供给控制器的标识符。您还可以使用 performSegueWithIdentifier:sender: 方法(它也实例化了视图控制器)。您应该查看 Apple 文档中的“在您的应用程序中使用视图控制器”部分。它还提到了子视图控制器与容器控制器同时实例化的事实。
编辑后:如果您将容器视图嵌入到另一个视图控制器中,则可以使用 self.childViewControllers 从包含控制器中引用该嵌入式视图的控制器(这将是一个数组,因此如果只有一个,您可以使用 lastObject 获取它) .
这是关于它的另一个线程:Access Container View Controller from Parent iOS
他们建议在prepareForSegue中保留参考或在self.childViewControllers中搜索嵌入的viewController
在继续使用这个问题的答案之前,您可能希望反映嵌入式事物是否真的需要成为视图控制器。
例如,如果您要嵌入一个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 标识符使用enum
case 意味着您已经拥有了编译器和工具,因此很难弄错 segue 名称。
在这种情况下,将 segue id 保持在private enum
范围extension
内似乎是合适的,因为在其他任何地方都不需要这些 segue(perform
例如,它们不能被编辑)。
我正在为嵌入式视图控制器使用隐式展开的类型,因为(在我的情况下)如果它们丢失,这是一个逻辑错误。
同样,我也很乐意强制转换目标视图控制器类型。同样,如果这些类型不相同,那将是一个逻辑错误。
票数最高的答案的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
.