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

时间:2009-09-28 12:47:10

标签: iphone uiview uiviewcontroller

对于googlers来说,这个Q-A现在已经过时了六年

正如Micky在下面和其他人提到的那样,现在每天都在iOS中使用容器来完成。


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

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

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

谢谢!

8 个答案:

答案 0 :(得分:86)

As of iOS 5,Apple现在允许您制作custom containers,以便将 UIViewController 添加到另一个 UIViewController ,尤其是通过{ {3}}因此确实可以嵌套 UIViewControllers

编辑:包括就地摘要,以避免链接破坏

我引用:

  

iOS提供了许多标准容器来帮助您整理应用。但是,有时您需要创建与任何系统容器提供的自定义工作流不匹配的自定义工作流。也许在您的愿景中,您的应用需要具有子视图控制器的特定组织,并具有专门的导航手势或它们之间的动画过渡。 要执行此操作,请实施自定义容器 - addChildViewController

...和

  

设计容器时,可以在容器,父容器和其他视图控制器及其子控件之间创建显式父子关系 - Tell me more...

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

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

干杯,

Micky Duncan

答案 1 :(得分:41)

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

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

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

In - (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];

享受

答案 2 :(得分:26)

这个答案对于旧版本的iOS是正确的,但现在已经过时了。您应该使用Micky Duncan的答案,其中包括自定义容器。

不要这样做! UIViewController的目的是驱动整个屏幕。它只是不合适,并没有真正添加你需要的东西。

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

将子视图NIB的所有者指向UIView的自定义子类。向此自定义子类添加contentView出口,并将其指向nib中的视图。在自定义子类中执行以下操作:

- (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:来构建子视图。)

答案 3 :(得分:17)

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

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

如果您愿意,可以将其作为代码段复制到您的代码中。因此,似乎无法理解代码替换格式,但它们将在Xcode中显示清晰:

    [self addChildViewController:<#viewControllerToAdd#>];
    [self.view addSubview:<#viewControllerToAdd#>.view];
    [<#viewControllerToAdd#> didMoveToParentViewController:self];
使用addChild自动调用

willMove。谢谢@iOSSergey

  

当您的自定义容器调用addChildViewController:方法时,它会自动调用视图控制器的willMoveToParentViewController:方法作为子项添加,然后再添加它。

答案 4 :(得分:6)

使用:

[self.view addSubview:obj.view];

答案 5 :(得分:1)

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

答案 6 :(得分:0)

您必须设置bounds属性以适合该帧。框架其超级视图属性,并限制视图本身坐标系中的框架。

答案 7 :(得分: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)