xcode storyboard Container View - 如何访问视图控制器
Posted
技术标签:
【中文标题】xcode storyboard Container View - 如何访问视图控制器【英文标题】:xcode storyboard Container View - How do I access the viewcontroller 【发布时间】:2012-10-27 19:51:19 【问题描述】:我正在尝试使用情节提要并让事情正常工作。我在现有视图之一中添加了一个容器视图。当我尝试在我的视图控制器.h
文件(ctrl-drag)中添加对此的引用时,我得到一个IBOutlet UIView *containerView
。如何获取对容器视图的视图控制器的引用?我需要容器视图控制器,这样我就可以将它设置为我的视图控制器的委托,以便它们可以相互“交谈”。
我的故事板设置为:
它在我的 .h 文件中被引用为:
.h 中的注意事项是 UIView,而不是我的 InstallViewController 视图。如何添加对视图控制器的引用?我需要能够设置它的委托。
【问题讨论】:
这是最后的,最终的,最后的,维护的,教程! ***.com/a/23403979/294884有一些小细节你需要知道,那里都解释的很详细很清楚。 【参考方案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 进行迭代。
【讨论】:
以上是关于xcode storyboard Container View - 如何访问视图控制器的主要内容,如果未能解决你的问题,请参考以下文章
ios - Xcode 9.4.1 在 main.storyboard 中卡住加载
Xcode 11,使用 Main.storyboard 修复的主界面 [重复]