【问题标题】:How to add an UIViewController's view as subview如何将 UIViewController 的视图添加为子视图
【发布时间】:2010-12-01 23:47:31
【问题描述】:

Google 员工请注意,此问答现已已过时六年

正如下面的 Micky 和其他人所提到的,现在在 iOS 中使用 Containers 每天都可以做到这一点。


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

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

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

谢谢!

【问题讨论】:

  • 我建议不要这样做。我为我的第一个 iPhone 应用程序做了这个,结果发现它是一个巨大的奇怪的混乱,更不用说它破坏了我试图用 Interface Builder 做的很多事情。在 3.0 文档中,他们特别说 - 每个屏幕 1 个视图控制器。你应该这样做!
  • 是的,即使我读过它,但问题是,如果我把它全部放在 1 个视图控制器中,那么它就是一大堆代码到 1 中,并且有很多 IBOutlets 和操作以及表格。因此,为了清晰和模块化,我尝试使用 2 个单独的视图控制器,第二个只是为主视图控制器提供视图并处理它自己的事件。这样主视图控制器就更干净了。我应该怎么做。我应该有多个带有导航控制器的视图控制器还是 1 个巨大的视图控制器。
  • 看看这个tutorial。它只是部分有效

标签: iphone uiview uiviewcontroller


【解决方案1】:

As of iOS 5,Apple 现在允许您创建 custom containers,以便将 UIViewController 添加到另一个 UIViewController,特别是通过 addChildViewController 等方法确实可以嵌套 UIViewControllers

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

我引用:

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

...和:

当您设计一个容器时,您会在容器、父级和其他视图控制器及其子级之间创建明确的父子关系 - Tell me more

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

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

【讨论】:

  • 在我对此的回答顶部添加了评论。
  • 你确定这是 iOS 5 吗?我在使用 iOS 5 时遇到了崩溃,但在 iOS 6 中运行良好。
  • iOS 5,我们在我们的应用中使用它
  • 谢谢米奇。事实证明,iOS 5 不支持的只是故事板嵌入 segue。
  • currentClientView的作用是什么?我在文档中完全看不懂。
【解决方案2】:

你也可以使用 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)

【讨论】:

    【解决方案3】:

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

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

    如果您愿意,可以将其作为 sn-p 复制到您的代码中。 SO 似乎不理解代码替换格式,但它们会在 Xcode 中显示干净:

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

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

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

    【讨论】:

    • 当您的自定义容器调用 addChildViewController: 方法时,它会在添加之前自动调用要添加为子视图控制器的 willMoveToParentViewController: 方法。
    • @iOSergey 你有那个链接吗?希望更新答案更正确。
    • 其实我也经常手动使用 willMoveToParent ,但是当我不小心看到苹果对这个函数的引用时,我感到很惊讶 :) developer.apple.com/library/ios/documentation/UIKit/Reference/…:
    • @iOSergey - 对不起,也许我很密集,但我没有在那里看到它:) 请更具体地指出我!你不是一个人总是打电话,当人们不可避免地告诉我把它放回去时,我想有一个很好的参考!再次感谢!
    • 在我链接的网站上搜索“willMoveToParentViewController”,展开“willMoveToParentViewController”参考并在讨论标题下最后一段 :) 我发布了完整链接,但由于某种原因它重定向到顶部。
    【解决方案4】:

    感谢这些人http://highoncoding.com/Articles/848_Creating_iPad_Dashboard_Using_UIViewController_Containment.aspx

    添加UIView,连接到header:

    @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];
    

    享受

    【讨论】:

    • 文档声明 didMoveToParentViewController 应该在 addChildViewController 之后调用,而不是之前。
    • 谢谢...很好的解决方案!
    【解决方案5】:

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

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

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

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

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

    【讨论】:

    • 虽然在当时是一个很好的答案,但这可能是自 iOS 5 以来过时的理念。请参阅下面的答案
    • 确实,这是几年前写的。我还没有使用自定义容器,但这似乎是解决这个问题的正确方法。
    • 感谢我的回答 Steven :)
    【解决方案6】:

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

    【讨论】:

    • 我试过了。它不起作用。我应该在界面生成器中做些什么吗?
    【解决方案7】:

    用途:

    [self.view addSubview:obj.view];
    

    【讨论】:

      【解决方案8】:

      您必须设置边界属性以适应该框架。 frame 其 superview 属性,bounds 将 frame 限制在 view 本身的坐标系中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-21
        • 1970-01-01
        相关资源
        最近更新 更多