iOS如何不从源代码将多个viewController添加到一个ViewController
我遇到了一些问题,因为我不知道如何做到这一点。请有人帮助我。
问题:
当我在 Xcode 中创建新项目时,我有一个带有 UIViewController 类的项目,并且一直创建。在这个 viewController 中,我有一个用于在 Xcode 中设计的 xib 文件。
我需要的是创建一些视图并在 Interface Builder 中设计它们,如下所示:
但我需要这些视图是 UIViewController,而不是 UIView。
该项目应如下所示:
所以我不知道如何在 IB 中执行此操作,但我可以从源代码中执行此操作ViewController.m
tab = [[TabBarController alloc] initWithNibName:@"mytestview" bundle:nil];
[tab.view setFrame:CGRectMake(100, 100, 400, 600)];
[self.view addSubview:tab.view];
但这不是我的视图,它是一个不同的对象,如果我想更改位置或大小,我必须通过代码来完成。我如何在 Interface Builder 中做同样的事情?
I'm having some problems because I don't know how it can be done. Someone help me please.
Problem:
I have a project with a UIViewController class with created all time when I create a new project in Xcode. In this viewController, I have a xib file for designing in Xcode.
What I need is to create some views and design them in Interface Builder like this:
But I need these views to be UIViewControllers, not UIViews.
The project should look like:
So I don't know how I can do this in IB but I can do it from source code in ViewController.m
tab = [[TabBarController alloc] initWithNibName:@"mytestview" bundle:nil];
[tab.view setFrame:CGRectMake(100, 100, 400, 600)];
[self.view addSubview:tab.view];
But it's not my views it's a different object, and if I want to change position or size I must do it from code. How I can do same things in Interface Builder?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
让我们考虑以下基于仅适用于 iPhone 的主详细应用程序的示例。
因此,在 Xcode 中新创建的项目中添加新的视图控制器:

我将其命名为 NewInsideViewController。不使用 xib 创建它:

打开 DetailViewController.xib。将视图控制器和视图(*)对象从库拖到对象区域,如下所示(我将视图的颜色更改为浅灰色):

选择此视图控制器并在身份检查器中将其类从 UIViewController 更改为 NewInsideController:

将我们的 View(*) 作为视图分配给 NewInsideController:

现在 IB 中的所有主要操作都已完成。我们需要在 DetailViewController 中创建 NewInsideController 的实例。您可以手动完成,但 Xcode 有一个很好的功能 - 拖放;)

我将此属性称为
myNewInsideController
,DetailViewController.h 如下所示: ,现在我们的 NewInsideController 已准备好工作并管理其视图。让我们向该视图添加按钮和操作以验证这一点:

在 NewInsideController 中的 IBAction 中编写一些代码。
运行程序。
Let's consider following example based on Master-Detailed Application for iPhone only.
So, add new view controller in newly created project in Xcode:

I called it NewInsideViewController. Create it without xib:

Open DetailViewController.xib. Drag View Controller and View(*) objects from library to Objects area like this (I changed view's color to LightGray):

Choose this View Controller and change its Class from UIViewController to NewInsideController at the Identity Inspector:

Assign our View(*) to NewInsideController as a view:

Now all main actions in IB finished. We need to create instance of NewInsideController in our DetailViewController. You can do it by hand, but Xcode has a nice feature - drag-n-drop ;)

I called this property as
myNewInsideController
and DetailViewController.h looks like this:Well, now our NewInsideController ready to work and manage its view. Let's add button and action to that view in order to verify this:

Write some code in IBAction in NewInsideController.
Run program.
如果我清楚地理解这个问题:
因此,简单地回答这个问题:假设您的项目中有一些自定义 UIViewController(每个视图控制器由 .h 和 .m 组成)。请记住,如果您将它们放在父级上下文中,它们不应该有自己的 XIB(您不能将 XIB 嵌套在 IB 中)。这里需要注意的是,您应该只将界面“布局”在一个位置。如果您想为每个子视图都有一个 XIB,这不是正确的方法。然而,您可以(不应该)做的是拥有多个自定义视图控制器,每个视图控制器都连接到位于父视图中的自己的视图,并且您可以将子视图控制器的出口设置为这个父视图。唷,有点乱。您需要注意的另一件事是,您的父视图控制器需要对其每个子视图控制器的引用,以便您能够以编程方式访问这些子控制器及其出口,因此对于每个子视图控制器添加视图控制器时,您还需要在父视图控制器中添加一个指向每个子视图控制器的 IBOutlet:
然后例如在第一个自定义子视图/控制器的视图上设置背景颜色:
打开您的父视图控制器IB。如果您查看可用对象的抽屉,您将找到一个通用 UIViewController 对象。将其拖到您的父视图控制器中(不是拖到它的视图画布上,而是拖到父 UIViewController 对象本身中,如 IB 构建器的左列所示)。选择您添加的通用视图控制器并将其类设置为您所需的 UIViewController 子类。现在,当您的 XIB 加载时,它将实例化您的自定义视图控制器的实例以及您添加到其画布中的任何内容。
最后,将通用 UIView 拖到画布上,将其放置在现有控制器的视图中(您的屏幕截图已显示此操作已完成)。右键单击您的自定义视图控制器,并将其“视图”出口连接到您添加的视图。
现在,当您运行时,您的自定义视图控制器在屏幕上有一个视图,它是您的自定义控制器子类的视图,并且您没有在代码中执行任何操作。
现在您已经完成了,请考虑它是否是最佳选择:嵌套视图控制器构建起来很混乱(正如您所见),并且不一定是一个好的设计决策:http://blog.carbon Five.com/2011/03/09/abusing-uiviewcontrollers/
虽然iOS5确实支持嵌套视图控制器,但我个人会避免使用它们。我重视一个最佳实践:一个屏幕 = 一个视图控制器。
If I understand the question clearly:
So, to answer the question succinctly: Let's assume you have a handful of custom UIViewController's in your project (each view controller consisting of a .h and a .m). Remember that you if you are laying these out in the context of the parent, they shouldn't have their own XIBs (you cannot nest XIBs in IB). What is important to note here is that you should only "layout" the interface in one location. If you want to have a XIB for each subview, this is not the correct approach. What you can (not should) do, however, is have several custom viewControllers, each connected to it's own view sitting within your parentView, and you can have the outlets of your sub view controller's set to objects in this parentView. Phew, kinda messy. The other thing you'd need to be aware of is that your parent view controller would need a reference to each of it's sub view controllers in order for you to be able to access those sub-controllers and their outlets programmatically, so for each sub view controller you add, you would also need to add an IBOutlet in your parent view controller pointing to each subviewController:
And then for example to set the background color on the view of your first custom subview/controller:
Open up your parent view controller in IB. If you look in your drawer of available objects, you'll find a generic UIViewController object. Drag this into your parent view controller (NOT onto it's views canvas, rather into the parent UIViewController object itself as seen in the left-column of IB builder). Select the generic view controller you've added and set it's class to your desired UIViewController subclass. Now, when your XIB loads, it will instantiate an instance of your custom view controller along with whatever you've added to it's canvas.
Finally, drag a generic UIView onto your canvas, placing it inside your existing controller's view (your screenshot already shows this as done). Right-click your custom view controller, and connect it's 'view' outlet to the view you added.
Now when you run, your custom view controller has a view that is on the screen that is the view of your custom controller subclass, and you didn't do any of it in code.
So now that you've done it, consider whether or not it is the best choice: Nested view controllers are messy to build (as you've seen) and aren't necessarily a good design decision: http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/
Although iOS5 does support nested view controllers, personally I'd avoid using them. I value a best practice dictating one screen = one view controller.
您永远不会想要获取已经在某个视图控制器控制下的视图,并使它们成为另一个视图控制器视图的子视图。
视图控制器是 MVC 设计模式中的 C 部分 - 它们负责控制视图(及其子视图)。您不能获取由控制器管理的视图,并将其作为不同控制器视图的子视图 - 如果您这样做,谁负责管理该视图就会变得模糊。
尽管这种“坚持”在技术上是可能的,但它会创建难以理解、难以维护的代码,最重要的是,由于谁负责管理视图的不明确以及由于以下事实,会导致错误: Apple 的视图/控制器框架不支持此功能。
例如:如果设备内存不足,Apple 会确保卸载当前未显示的视图。 Apple 依靠视图控制器层次结构来了解何时可以卸载视图。如果将视图控制器的视图粘贴到另一个视图控制器的视图中,则即使该视图不可见,也很可能永远不会被卸载。
不要破坏视图控制器层次结构,而是执行以下操作之一:
-viewDidLoad:
中以编程方式添加它们,或者(罕见)覆盖 <代码>-loadView。破坏视图控制器层次结构的坏主意确实很常见,并且经常在第三方中看到,可能是因为它是如此简单且看似简单。不幸的是,这会导致上述错误:-(
我真的建议每个参与此线程和评论的人阅读 Apple 的 查看控制器编程指南,并观看 WWDC 2011 “查看控制器遏制”视频。
You never, EVER, want to take views which are already under the control of a certain view controller, and make them subviews of another view controller's view.
View Controllers are the C part in the MVC design pattern - They are in charge of controlling a view (and its subviews). You can't take a view which is being managed by a controller, and stick it as a subview of a different controller's view - If you do that, it becomes ambigous who is responsible to manage this view.
Even though this "sticking" might be possible technically, it creates code which is hard to understand, hard to maintain, and most importantly - will cause bugs due to the unclarity of who is responsible to manage the view, and due to the fact that Apple's View/Controller framework doesn't support this.
For example: If the device is low on memory, Apple makes sure to unload views which are not currently displayed. Apple relies on the view controllers hierarchy to know when it can unload views. If you stick the view controller's view in another view controller's view, it's very likely that the view will never be unloaded even if it isn't visible.
Instead of breaking the view controller hierarchy, do one of the following:
-viewDidLoad:
to add them programatically, or (rarer) override-loadView
.The bad idea of breaking a view controller hierarchy is indeed very common and often seen in 3rd parties, probably because it's so easy and seemingly straightforward. Unfortunately this causes the aforementioned bugs :-(
I really recommend to everyone participating in this thread and comments to read Apple's View Controller Programming Guide, and watch WWDC 2011 "View Controller Containment" video.