要从代码创建两个视图控制器之间的父/子关系,基本上只需执行以下操作:
[self addChildViewController:childViewController];
[self.view addSubview:childViewController.view];
Run Code Online (Sandbox Code Playgroud)
其中self是父视图控制器.
但是,如果我想完全从Interface Builder创建相同的关系呢?
或者换句话说:有没有办法使用Interface Builder重新创建方法addChildViewController的行为?
我没有找到很多关于这方面的文档,这是一篇关于该主题的未解决的帖子:https://devforums.apple.com/message/455758#455758
如果没有正确设置addChildViewController关系,任何旋转方法都不会转发到我的子视图控制器,这是我的问题所在.
这就是我在IB中所做的:
图片中的第一个"View"对象是我的父视图控制器的视图,而突出显示的"View"是子视图控制器的视图("Item View Controller").

容器控制器还通过另外的IBOutlet保留其子实例:
@property (nonatomic, strong) IBOutlet ItemsViewController *itemsViewController;
Run Code Online (Sandbox Code Playgroud)
谢谢
更新1:如果我在容器控制器的viewDidLoad中手动设置父/子关系,则所有旋转方法都会正确转发给子项.
[self addChildViewController:self.itemsViewController];
Run Code Online (Sandbox Code Playgroud)
但我真的不知道这是否是正确的做法,因为我想用IB做所有事情.
更新2:感谢@micantox提示他使用对象库中的"容器视图",我已将我的xib文件转换为Storyboard,现在子视图控制器已添加到其父级,所以我没有必要使用addChildViewController从代码中手动添加它,并按预期转发旋转方法.
"容器视图"基本上实现了嵌入segue,仅支持iOS 6.
这是我的Storyboard更新的截图:

interface-builder uiviewcontroller uistoryboardsegue childviewcontroller container-view
我已经为iPhone创建了一个侧视图菜单,我已经使用集装箱船概念在父视图控制器中添加子视图控制器.当用户点击导航栏上的菜单按钮时,我只需更改子视图控制器的框架,使其像一个显示菜单一样设置动画,以便子视图控制器将其框架的一半剪裁到右侧.
现在我的问题是每当用户点击子视图控制器的任何部分时我只想通知其父视图控制器触发事件已在其子视图控制器上触发,以便父视图控制器可以重置子视图控制器的帧以使其动画化喜欢关闭半显示菜单.
我使用了tap手势并将其添加到子视图控制器子视图的每个子视图中.因此,在任何子视图上点击手势都会通知父视图控制器有关触摸事件的信息.
触摸事件适用于子视图控制器的主视图,但任何按钮上的任何触摸都无法识别TAP事件.
我不知道我在哪里误会.请帮助我如何通知父视图控制器其子视图控制器中的任何触摸.提前致谢.
iphone parentviewcontroller touch-event ios childviewcontroller
我在UITableView中的Container视图中使用UISearchController.我正在添加这样的搜索栏:
self.resultsTableController = [self.storyboard instantiateViewControllerWithIdentifier:NSStringFromClass([ResultViewController class])];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
self.searchController.searchResultsUpdater = self;
[self.searchController.searchBar sizeToFit];
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.tableView.tableHeaderView = self.searchController.searchBar;
self.resultsTableController.tableView.delegate = self;
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = YES;
self.searchController.searchBar.delegate = self;
self.definesPresentationContext = NO;
Run Code Online (Sandbox Code Playgroud)
请参阅以下屏幕截图.它隐藏了搜索栏上方的所有搜索结果:

请帮帮我,为什么我得到这个?
uitableview childviewcontroller childviews ios8 uisearchcontroller
我有一个应用程序,它有 UITabbarController 作为初始窗口(登录后我将它设置为 rootViewController)
这个 tabbarController 有 4 个不同的选项卡,它们都是嵌入在 UINavigationController 中的 UIViewController。
在我的 tabbarController 中,当我进行初始配置时,我设置了如下选项卡:
首先我创建viewControllers:
let tableViewController1 = tableViewController1(nibName: "tableViewController1", bundle: nil)
let tableViewController2 = tableViewController2(nibName: "tableViewController2", bundle: nil)
let tableViewController3 = tableViewController3(nibName: "tableViewController3", bundle: nil)
let profileViewController = ProfileViewController(nibName: "ProfileViewController", bundle: nil)
Run Code Online (Sandbox Code Playgroud)然后我将它们嵌入到 navigationControllers 中:
let navController1 = UINavigationController(rootViewController: tableViewController1)
let navController2 = UINavigationController(rootViewController: tableViewController2)
let navController3 = UINavigationController(rootViewController: tableViewController3)
let navController4 = UINavigationController(rootViewController: profileViewController)
Run Code Online (Sandbox Code Playgroud)最后,将 navigationControllers 添加为 tabbarController 的 viewControllers
viewControllers = [navController1,navController2,navController3,navController4]
我在网上查了一下,这种使用方式似乎是正确的。例如:https : //medium.com/@ITZDERR/uinavigationcontroller-and-uitabbarcontroller-programmatically-swift-3-d85a885a5fd0 …
crash uinavigationcontroller childviewcontroller view-hierarchy swift
最新更新:我创建了一个全新的项目,其构建方式与下面完全相同.然而,这个测试项目实际上工作得很好,即使它看起来是一样的...我注意到的一件事是破坏版本中的父视图控制器在-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event点击子视图控制器的视图时接收...在工作版本中,子视图控制器接收事件应该......就好像父视图阻止子视图或其他东西..?
进度更新:在拧了一下后,我发现直接将帧分配给子视图控制器时它可以正常工作.但是,我必须使用autolayout创建我的项目,这就是我所做的.出于某种原因,autolayout导致子视图控制器的视图无响应...
目前我有一个只有1个childviewcontroller的viewcontroller.childviewcontroller的视图显示得很好但我根本无法与childViewController进行交互.childViewController有几个UIButtons,但它们不响应点击.
我尝试在父视图控制器和子视图控制器中进行测试.
(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Touched!");
}
Run Code Online (Sandbox Code Playgroud)
单击子视图控制器视图的框架时,此方法在父视图控制器中响应,但不在子视图控制器中响应.
子视图控制器在直接创建它并将其设置为应用程序委托中的根视图控制器时也可以正常工作.
我在父视图控制器中使用的代码:
(void) viewDidLoad
{
[super viewDidLoad];
self.detailPageVC = [[GoalDetailsPageViewController alloc] init];
[self.view addSubview:self.detailPageVC.view];
[self addChildViewController:self.detailPageVC];
[self.detailPageVC didMoveToParentViewController:self];
}
Run Code Online (Sandbox Code Playgroud)
感谢您帮助新手!:)
这对我来说是一个严重的问题.在具有多层子视图控制器的代码库上工作大约4-5层 - 这是一个平板电脑应用程序,在视图控制器之间具有非常高的解耦程度.第5层子视图控制器想要向顶级视图控制器发送消息以显示模态.第4层和第3层也有不同的消息,所以基本上现在我有4个协议,从嵌入到祖先viewcontroller深处的子视图控制器发送消息变得非常复杂.有更简单的方法吗?
我们考虑过使用NSNotification但不是特别喜欢它,因为它很难调试它,并且订阅不是我们控制范围内的明确依赖.我们还考虑过使用单例,但静态和单例是邪恶的(对吧?)并导致状态和并发问题.
任何帮助表示赞赏.此外,我意识到我意识到这是一个稍微开放的基于设计的问题,但它有一个非常具体的用例(如上所述).
假设我想要实现Pinterest的pin页面,就像这样:

这是我的方法:
UICollectionViewController,pin的页面是一个UICollectionViewCell然后出现了问题:如何重用子视图控制器?
一些伪代码:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
Pin *pin = self.dataSource[indexPath.row];
// i have to create a new childVC, based on different indexPath.
UITableViewController *pinInfoViewController = [[pinInfoViewController alloc] initWithPin:pin];
[cell updatePinViewWithPin:pin];
[self addChildViewController:pinInfoViewController];
// Add waterfall view controller
}
Run Code Online (Sandbox Code Playgroud)
每次调用此方法时,都会创建一个新的子视图控制器,它没问题,或者如何改进它?
我有一个拆分视图控制器,当用户单击表视图中的单元格时,该应用程序会显示一个带有容器视图和段控件的视图控制器,以在两个子视图控制器之间切换.
第一个子视图控制器是Collection View Controller.在Collection View的每个单元格中都有一个单词.
该视图如下所示:
我使用此代码以编程方式添加子视图控制器(来自详细视图控制器,子视图的容器):
override func viewDidLoad() {
self.currentViewController = self.storyboard?.instantiateViewController(withIdentifier: "WordCollectionViewControllerID")
(self.currentViewController as! WordCollectionViewController).text = self.text
self.currentViewController?.view.translatesAutoresizingMaskIntoConstraints = false
self.addChildViewController(self.currentViewController!)
self.addSubview(subView: self.currentViewController!.view, toView: self.textContainerView)
self.currentViewController?.view.layoutIfNeeded()
self.currentViewController?.didMove(toParentViewController: self)
super.viewDidLoad()
}
func addSubview(subView: UIView, toView parentView: UIView) {
parentView.addSubview(subView)
var viewBindingsDict = [String: AnyObject]()
viewBindingsDict["subView"] = subView
parentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[subView]|", options: [], metrics: nil, views: viewBindingsDict))
parentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[subView]|", options: [], metrics: nil, views: viewBindingsDict))
}
Run Code Online (Sandbox Code Playgroud)
以下是使用分段控件在两个子视图之间切换的代码:
@IBAction func changeChildViewController(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
let newViewController …Run Code Online (Sandbox Code Playgroud) 当在横向iPhone X上滑动儿童ViewController时,在安全区域方面遇到困难。
我有一个根ViewController,其视图之一是可移动的,并且包含一个嵌入式子ViewController。真正的应用程序是滑动的侧栏菜单UI。这里的示例代码是简化版本。
如果表格位于屏幕的左侧,则“安全区域”布局规则会将其单元格contentView插入项推到右侧以允许出现缺口。正确。但是,如果我将子级ViewController移离屏幕的左边缘,则子级的插图不会更新以重播内容。
我已经意识到,实际上,如果子ViewController在其最终位置完全显示在屏幕上,则一切正常。如果其中任何部分不在屏幕上,则不会发生“安全区域”更新。
这是显示此问题的示例代码。这适用于标准的Single View App Xcode模板项目:用显示的代码替换ViewController文件代码。运行时,向右滑动表格会将其从屏幕的左边缘移动到右边缘。
参见“ constraint(...,乘数:0.5)”行。这设置了相对于屏幕的可移动视图的宽度。值为0.5时,表格完全适合屏幕,并且安全区域会随着移动而更新。左停靠时,表格单元格遵循“安全区域”插图,右停靠时,表格单元格中没有正确的额外插图。
一旦乘数超过0.5(甚至在0.51时),表格的右滑动部分便不在屏幕上。在这种情况下,不会发生安全区域更新,因此表格单元格内容插入太大了-即使表格的左边缘现在不在安全区域附近,它仍然具有44像素的安全区域插入。
更令人困惑的是,如果UIViews不是UIViewController的视图,则布局似乎可以很好地工作。但是我需要它与UIViewControllers一起使用。
谁能解释如何让子级ViewController遵守正确的安全区域?谢谢。
复制代码:
class ViewController: UIViewController {
var leftEdgeConstraint : NSLayoutConstraint!
var viewThatMoves : UIView!
var myEmbeddedVC : UIViewController!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.gray
self.viewThatMoves = UIView()
self.viewThatMoves.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(self.viewThatMoves)
// Relayout during animation work with multiplier = 0.5
// With any greater value, like 0.51 (meaning part of the view is offscreen), relayout does not happen
self.viewThatMoves.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.5).isActive = true
self.viewThatMoves.heightAnchor.constraint(equalTo: …Run Code Online (Sandbox Code Playgroud) 我正在尝试将UIViewController子视图控制器添加到选项卡栏控制器。参见下面的代码:
guard let vc = self.storyboard?.instantiateViewController(withIdentifier: "MyAlertViewController") as? MyAlertViewController else
{
return
}
let base: UITabBarController = tabBarController!
base.addChildViewController(vc)
vc.view.frame = base.view.bounds
base.view.addSubview(vc.view)
vc.didMove(toParentViewController: base)
Run Code Online (Sandbox Code Playgroud)
它有效,但有一个我无法解决的问题:MyAlertViewController添加到选项卡栏控制器的viewControllers数组中,有时它甚至显示为选项卡栏项目。有办法解决这个问题吗?谢谢。
ios ×7
swift ×3
childviews ×1
crash ×1
ios6 ×1
ios8 ×1
iphone ×1
iphone-x ×1
objective-c ×1
touch-event ×1
uievent ×1
uiresponder ×1
uitableview ×1