如何将UIViewController的视图添加为子视图


75

请注意,Google的质量检查已过期六年了

就像下面的Micky和其他人提到的那样,现在可以每天在iOS中使用Containers完成此操作。


我有一个ViewController,它控制许多子视图。当我单击一个按钮时,我初始化了另一个viewcontroller并将其视图显示为该视图的子视图。但是,子视图超出了子视图框架的范围,并且实际上填充了整个屏幕。

有什么事吗 我认为问题是UIViewController的视图有一个框架(0,0,320,460),因此充满了整个屏幕(尽管只有在子视图框架范围内被触摸时,它才会接收触摸事件)。如何调整框架的大小以适合子视图。

简而言之,我需要帮助,将一个视图控制器的视图作为子视图添加到另一个视图控制器的视图中。

谢谢!


1
我建议不要这样做。我为我的第一个iPhone应用程序执行了此操作,结果发现它是一个巨大的怪异混乱,更不用说它破坏了我尝试使用Interface Builder处理的许多东西。在3.0文档中,他们专门说-每个屏幕1个View Controller。你应该做这个!
bpapa

是的,甚至我都读过它,但是问题是,如果我将所有内容都放在1个viewcontroller中,则是将很多代码合并为1,并且有很多IBOutlet,动作和表。因此,为了清晰和模块化,我尝试使用2个独立的视图控制器,第二个仅向主视图控制器提供视图并处理其自身的事件。这样,主视图控制器就更干净了。我应该怎么做呢。我应该有多个带有nav控制器的视图控制器还是1个巨大的视图控制器。
精子

看一下本教程。它只是部分起作用
Casebash

Answers:


86

从iOS 5开始,Apple现在允许您制作自定义容器,目的是为了将UIViewController添加到另一个UIViewController中,尤其是通过诸如addChildViewController之类的方法,因此确实可以嵌套UIViewControllers

编辑:包括就地摘要,以避免链接断开

我引用:

iOS提供了许多标准容器来帮助您组织应用程序。但是,有时您需要创建一个自定义工作流程,该工作流程与任何系统容器提供的工作流程都不匹配。也许在您看来,您的应用需要特定的子视图控制器组织,并在它们之间进行专门的导航手势或动画转换。为此,您实现一个自定义容器-告诉我更多...

...和:

设计容器时,您在容器,父级和其他视图控制器及其子级之间创建显式的父子关系-告诉我更多

示例(由Apple文档提供)将另一个视图控制器的视图添加到容器的视图层次结构中

- (void) displayContentController: (UIViewController*) content
{
   [self addChildViewController:content];                 
   content.view.frame = [self frameForContentController]; 
   [self.view addSubview:self.currentClientView];
   [content didMoveToParentViewController:self];          
}

2
在我对此的回答的顶部添加了评论。
史蒂芬·费舍尔

您确定这是iOS 5吗?我越来越崩溃与iOS 5,但它工作在IOS 6精细
史蒂芬费舍尔

iOS 5,我们在应用程序中使用它
MickyD 2013年

谢谢米奇。事实证明,这只是一个未在iOS的支持5.故事板嵌入SEGUE
史蒂芬费舍尔

3
的作用是currentClientView什么?我在文档中根本看不懂。
Iulian Onofrei 2015年

41

感谢这些家伙,我做到了http://highoncoding.com/Articles/848_Creating_iPad_Dashboard_Using_UIViewController_Containment.aspx

添加UIView,将其连接到标题:

@property (weak, nonatomic) IBOutlet UIView *addViewToAddPlot;

在-(void)viewDidLoad中执行以下操作:

ViewControllerToAdd *nonSystemsController = [[ViewControllerToAdd alloc] initWithNibName:@"ViewControllerToAdd" bundle:nil];
    nonSystemsController.view.frame = self.addViewToAddPlot.bounds;
    [self.addViewToAddPlot addSubview:nonSystemsController.view];
    [self addChildViewController:nonSystemsController];
    [nonSystemsController didMoveToParentViewController:self];

请享用


3
文档指出didMoveToParentViewController应该在addChildViewController之后而不是之前调用。
亚伦

谢谢...很好的解决方案!
jalopezsuarez 2014年

26

此答案对于旧版本的iOS是正确的,但现在已过时。您应该使用Micky Duncan的答案,该答案涵盖了自定义容器。

不要这样!的目的UIViewController是驱动整个屏幕。它只是不适合此操作,它并没有真正添加您需要的任何内容。

您需要的只是拥有您的自定义视图的对象。只需使用一个子类UIView自身即可将其添加到窗口层次结构中,并且内存管理是全自动的。

为子视图的NIB所有者指定一个自定义子类UIViewcontentView在此自定义子类中添加一个插座,并将其指向笔尖内的视图。在自定义子类中,执行以下操作:

- (id)initWithFrame: (CGRect)inFrame;
{
    if ( (self = [super initWithFrame: inFrame]) ) {
        [[NSBundle mainBundle] loadNibNamed: @"NibNameHere"
                                      owner: self
                                    options: nil];
        contentView.size = inFrame.size;
        // do extra loading here
        [self addSubview: contentView];
    }
    return self;
}

- (void)dealloc;
{
    self.contentView = nil;
    // additional release here
    [super dealloc];
}

(我假设您在这里initWithFrame:用来构造子视图。)


2
虽然在当时相当不错的答案,这也许是过时的理念,因为iOS的5.见我的回答如下
MickyD

1
确实,这是几年前写的。我还没有使用自定义容器,但这似乎是解决此问题的正确方法。
史蒂芬·费舍尔

感谢您插入我的答案史蒂文:)
MickyD 2013年

17

我觉得所有这些答案都有些不完整,因此这是将viewController的视图添加为另一个viewController的视图的子视图的正确方法:

    [self addChildViewController:viewControllerToAdd];
    [self.view addSubview:viewControllerToAdd.view];
    [viewControllerToAdd didMoveToParentViewController:self];

如果需要,可以将其作为代码段复制到代码中。SO似乎不了解代码替换格式,但是它们将在Xcode中清晰显示:

    [self addChildViewController:<#viewControllerToAdd#>];
    [self.view addSubview:<#viewControllerToAdd#>.view];
    [<#viewControllerToAdd#> didMoveToParentViewController:self];

将使用addChild自动调用willMove。谢谢@iOSSergey

当您的自定义容器调用addChildViewController:方法时,它将在添加之前自动调用视图控制器的willMoveToParentViewController:方法作为子级添加。


当您的自定义容器调用addChildViewController:方法时,它将在添加之前自动调用视图控制器的willMoveToParentViewController:方法作为子级添加。
iOSergey '16

@iOSergey您有链接吗?很想将答案更新为更正确的答案。
洛根

我其实一直习惯用willMoveToParent以及手动,但是当我不小心读苹果提到这一功能感到意外:) developer.apple.com/library/ios/documentation/UIKit/Reference/...
iOSergey

@iOSergey-抱歉,也许我正在密密麻麻,但是我在那儿看不到它。您并不总是一个人打电话,当人们不可避免地告诉我放回去时,我想提供很好的参考!再次感谢!
罗根

在我链接的网站上搜索“ willMoveToParentViewController”,使用“ willMoveToParentViewController”引用,并在“讨论”标题下的最后一段:)我发布了完整链接,但由于某种原因,其重定向到顶部。
iOSergey


1

更改的帧大小viewcontroller.view.frame,然后将其添加到子视图。[viewcontrollerparent.view addSubview:viewcontroller.view]


我尝试过这个。没用 我应该在界面构建器中做些什么吗?
精子

0

您必须设置bounds属性以适合该框架。框架其superview属性,并且边界将框架限制在视图本身的坐标系中。


0

您可以将PopupController用于将UIViewController显示为子视图的SDK的同一对象。 PopupController

这是相同的示例代码

popup = PopupController
        .create(self.navigationController!)
        .customize(
            [
                .layout(.center),
                .animation(.fadeIn),
                .backgroundStyle(.blackFilter(alpha: 0.8)),
                .dismissWhenTaps(true),
                .scrollable(true)
            ]
        )
        .didShowHandler { popup in
        }
        .didCloseHandler { popup in
    }
    let container = MTMPlayerAndCardSelectionVC.instance()
    container.closeHandler = {() in
        self.popup.dismiss()
    }

    popup.show(container)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.