【问题标题】:xcode storyboard Container View - How do I access the viewcontrollerxcode storyboard Container View - 如何访问视图控制器
【发布时间】:2012-10-27 19:51:19
【问题描述】:

我正在尝试使用情节提要并让事情正常工作。我在现有视图之一中添加了一个容器视图。当我尝试在我的视图控制器.h 文件(ctrl-drag)中添加对此的引用时,我得到一个IBOutlet UIView *containerView。如何获取对容器视图的视图控制器的引用?我需要容器视图控制器,这样我就可以将它设置为我的视图控制器的委托,以便它们可以相互“交谈”。

我的故事板设置为:

它在我的 .h 文件中被引用为:

.h 中的注意事项是 UIView,而不是我的 InstallViewController 视图。如何添加对视图控制器的引用?我需要能够设置它的委托。

【问题讨论】:

  • 这是最后的,最终的,最后的,维护的,教程! stackoverflow.com/a/23403979/294884有一些小细节你需要知道,那里都解释的很详细很清楚。

标签: ios objective-c xcode uiviewcontroller container-view


【解决方案1】:

还有另一种解决方案,通过为嵌入 segue 指定一个标识符并在方法 prepareForSegue: 中检索相应的视图控制器

这种方式的优点是您不需要依赖添加子视图控制器的特定顺序,因为每个子视图控制器都通过唯一的 segue 标识符嵌入。

2013-01-17 更新 - 示例

- (void) prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
    // -- Master View Controller
    if ([segue.identifier isEqualToString:c_SegueIdEmbedMasterVC])
    {
        self.masterViewController = segue.destinationViewController;
        // ...
    }
    // -- Detail View Controller
    else if ([segue.identifier isEqualToString:c_SegueIdEmbedDetailVC])
    {
        self.detailViewController = segue.destinationViewController;
        // ...
    }
}

c_SegueIdEmbedMasterVC & c_SegueIdEmbedDetailVC 是与故事板中定义的 segue ID 的对应 ID 对应的常量。

【讨论】:

  • 抱歉更新晚了。我相信你在此期间自己解决了这个问题,但最终示例代码会在未来帮助其他人。
  • 大神解答。我之前尝试过这个技巧,只有在阅读了这个答案后,我才意识到它只有在你设置 Segue Identifiers 时才有效。但是我会使用 isKindOfClass: 代替。
  • 为什么会有两个视图控制器(detail 和 master)?它不只是容器中的一个视图控制器吗?你指的其他segue是什么?
  • @shim:在我的示例项目中,我有一种拆分视图,其中一个主视图控制器和一个详细视图控制器托管在 2 个单独的容器视图中 - 因此是两个视图控制器。
  • 遗憾的是,这是获取子视图控制器引用的最佳方式。故事板的重点是减少这样的样板代码。我可以用更少的代码行在viewDidLoad 中添加子视图控制器,它会比这更易于维护。有人知道这是否在 XCode 6 中修复了吗?
【解决方案2】:

当你添加一个容器视图时,xcode 会调用 UIViewController 方法addChildViewController:

在您的情况下,您可以让容器 ViewController 在 SplashViewController 的 childViewControllers 列表中查找它,如下所示:

for (UIViewController *childViewController in [self childViewControllers])
{
    if ([childViewController isKindOfClass:[InstallViewController class]])
    {
        //found container view controller
        InstallViewController *installViewController = (InstallViewController *)childViewController;

        //do something with your container view viewcontroller

        break;
    }
}

我昨天也有同样的疑问:)

【讨论】:

  • 我正在尝试做类似的事情,但我没有得到 InstallViewController *installViewController = (InstallViewController *)vc; 中的“vc”;
  • 你是对的,它应该是“childViewController”。我刚刚在帖子中修复了。很抱歉花了这么多时间来回复。
  • 这种方法对我来说有点像“解决方法”。不是吗?
  • 嗯,它成功了 :) 当容器视图被添加到另一个视图时,prepareForSegue 方法是否被调用?
【解决方案3】:

Vitor Franchi 的答案是正确的,但可以更高效、更方便。尤其是在多次访问子视图控制器时。

创建一个只读属性

@interface MyViewController ()
@property (nonatomic, weak, readonly) InstallViewController *cachedInstallViewController;
@end

然后创建一个方便的getter方法

- (InstallViewController *)installViewController
{
    if (_cachedInstallViewController) return _cachedInstallViewController;

    __block InstallViewController *blockInstallViewController = nil;
    NSArray *childViewControllers = self.childViewControllers;
    [childViewControllers enumerateObjectsUsingBlock:^(id childViewController, NSUInteger idx, BOOL *stop) {

        if ([childViewController isMemberOfClass:InstallViewController.class])
        {
            blockInstallViewController = childViewController;
            *stop = YES;
        }
    }];

    _cachedInstallViewController = blockInstallViewController;

    return _cachedInstallViewController;
}

从现在开始以这种方式访问​​子视图控制器

[self.installViewController doSomething];

【讨论】:

    【解决方案4】:
    UIView* viewInsideOfContainer = installerView.subviews[0];
    

    将为您提供控制器 UIView 引用的 UIViewController 内部的 UIView。您可以将子视图转换为从 UIView 继承的任何类型。

    【讨论】:

    • 我不确定我是否喜欢做出这样的假设,但知道它很有用。
    • 这不是通用的方法:视图层次结构可以改变,这种方法不起作用。
    【解决方案5】:

    如果 nib 被加载,它将调用 addChildViewController 作为初始化过程的一部分

    所以一个高效的解决方案也可以是覆盖

    - (void)addChildViewController:(UIViewController *)childController
    

    在那里你可以抓住你的 childController 例如通过比较其 Class 并将其分配给属性 / ivar

    -(void)addChildViewController:(UIViewController *)childController
    {
        [super addChildViewController:childController];
    
        if([childController isKindOfClass:[InstallViewController class]])
        {
            self.installViewController = (InstallViewController *)childController;
        }
    

    }

    这将使您免于通过 childViewControllers 进行迭代。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-25
      • 1970-01-01
      • 2012-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多