iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

时间:2023-01-12 17:54:56

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.

我有一个项目,它有一个UIViewController类,当我在Xcode中创建一个新项目时,它一直被创建。在这个viewController中,我有一个用于在Xcode中设计的xib文件。

iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

What I need is to create some views and design them in Interface Builder like this:

我需要的是创建一些视图并在接口构建器中设计它们:

iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

But I need these views to be UIViewControllers, not UIViews.

但是我需要这些视图是UIViewControllers,而不是uiview。

The project should look like: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

项目应如下:

So I don't know how I can do this in IB but I can do it from source code in ViewController.m

我不知道如何在IB中做这个但我可以从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?

但它不是我的视图它是一个不同的对象,如果我想改变位置或大小,我必须用代码来做。如何在接口构建器中做同样的事情?

3 个解决方案

#1


3  

Let's consider following example based on Master-Detailed Application for iPhone only.

让我们考虑以下示例,它基于只适用于iPhone的主详细应用程序。

So, add new view controller in newly created project in Xcode: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

因此,在Xcode新创建的项目中添加新的视图控制器:

I called it NewInsideViewController. Create it without xib: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

我叫它NewInsideViewController。创建它没有xib:

Open DetailViewController.xib. Drag View Controller and View(*) objects from library to Objects area like this (I changed view's color to LightGray): iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

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

Choose this View Controller and change its Class from UIViewController to NewInsideController at the Identity Inspector: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

选择此视图控制器,并将其类从UIViewController更改为标识检查器的NewInsideController:

Assign our View(*) to NewInsideController as a view: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

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

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 ;) iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

现在IB的所有主要动作都完成了。我们需要在DetailViewController中创建NewInsideController的实例。您可以手工完成,但是Xcode有一个很好的特性—拖放;)

I called this property as myNewInsideController and DetailViewController.h looks like this:

我把这个属性叫做myNewInsideController和DetailViewController。h是这样的:

#import <UIKit/UIKit.h>
#import "NewInsideController.h"

@interface DetailViewController : UIViewController

@property (strong, nonatomic) id detailItem;
@property (strong, nonatomic) IBOutlet NewInsideController *myNewInsideController;

@property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
@end

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: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

现在,我们的NewInsideController已经准备好工作并管理它的视图了。让我们为这个视图添加按钮和操作,以验证这一点:

Write some code in IBAction in NewInsideController.

在NewInsideController的IBAction中编写一些代码。

- (IBAction)insideButtonClick:(id)sender {
    float rPart = arc4random()%100/100.0f;
    float gPart = arc4random()%100/100.0f;    
    self.view.backgroundColor = [UIColor colorWithRed:rPart green:gPart blue:0.5f alpha:1.0f];
}

Run program.

运行程序。

#2


0  

If I understand the question clearly:

如果我清楚地了解这个问题:

  1. You have a parent view and controller, coming from a XIB.
  2. 您有一个父视图和控制器,来自一个XIB。
  3. You have placed subviews into the parent view.
  4. 您已经将子视图放置到父视图中。
  5. You're wanting each subview placed into the parent view to have it's own (custom) controller, but you don't know how to add view controller's to your hierarchy (XCode will not let you drag view controllers into a view's canvas).
  6. 您希望放置在父视图中的每个子视图都有自己的(自定义的)控制器,但是您不知道如何将视图控制器添加到层次结构中(XCode不允许将视图控制器拖放到视图的画布中)。

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:

为了简洁地回答这个问题我们假设你的项目中有一些自定义的UIViewController(每个视图控制器由。h和。m组成)请记住,如果您在父类的上下文中列出这些,它们不应该有自己的xib(您不能在IB中嵌套xib)。这里需要注意的是,您应该只在一个位置“布局”接口。如果您希望每个子视图都有XIB,那么这不是正确的方法。但是,您可以(不应该)做的是,有几个自定义的viewcontrollerde,每个自定义的viewcontrollerde连接到它位于parentView中的自己的视图,您可以将子视图控制器的outlet设置为这个parentView中的对象。哇,有点乱。另一件事你需要注意的是,你的父视图控制器需要引用每个子视图控制器为了你能够以编程方式访问这些sub-controllers和网点,对每个子视图控制器添加,你还需要添加一个IBOutlet父视图控制器指向每个subviewController:

 ParentViewController.h
 @property (nonatomic, weak) IBOutlet CustomUIViewController *firstCustomController;

And then for example to set the background color on the view of your first custom subview/controller:

然后,例如,在你的第一个自定义子视图/控制器的视图上设置背景颜色:

ParentViewController.m
[[[self firstCustomController] view] setBackgroundColor:[UIColor whiteColor]];

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.

在IB中打开父视图控制器。如果你查看可用对象的抽屉,你会发现一个通用的UIViewController对象。将它拖到父视图控制器中(不是拖到它的视图画布上,而是拖到父UIViewController对象本身中,如图ibbuilder的左列所示)。选择添加的通用视图控制器,并将其类设置为所需的UIViewController子类。现在,当您的XIB加载时,它将实例化自定义视图控制器的一个实例,以及您添加到它的画布上的内容。

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.

最后,将一个通用的UIView拖到画布上,并将其放在现有控制器的视图中(您的屏幕截图已经显示了这一点)。右键单击自定义视图控制器,将它的“视图”outlet连接到添加的视图。

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/

既然已经完成了,那么考虑一下它是否是最好的选择:嵌套视图控制器构建起来很麻烦(如您所见),而且不一定是一个好的设计决策: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.

虽然iOS5确实支持嵌套视图控制器,但我个人不会使用它们。我看重的是口述一个屏幕=一个视图控制器的最佳实践。

iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

#3


-1  

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.

视图控制器是MVC设计模式中的C部分——它们负责控制视图(及其子视图)。您不能使用控制器管理的视图,并将其作为一个不同的控制器视图的子视图——如果您这样做了,那么它就会变得很复杂,谁负责管理这个视图。

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.

尽管这种“粘贴”可能在技术上是可能的,但它会创建难以理解的代码,很难维护,而且最重要的是,它会导致bug,原因是谁负责管理视图,以及苹果的视图/控制器框架不支持这一事实。

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:

与其破坏视图控制器的层次结构,不如做以下事情:

  1. Just add subviews to your view normally, either in interface builder, or in -viewDidLoad: to add them programatically, or (rarer) override -loadView.
  2. 通常,只需在接口构建器或-viewDidLoad中向视图添加子视图:以编程方式添加它们,或者(更少)覆盖-loadView。
  3. Use view controller containment, either with Apple's ready-made ones (UINavigationController,UISplitViewController etc.) or with your own container view controllers (iOS>5).
  4. 使用视图控制器容器,要么是苹果的现成的(UINavigationController,UISplitViewController等),要么是你自己的容器视图控制器(iOS>5)。
  5. Display view controllers modally.
  6. 显示视图控制器程序地。

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.

我真的建议所有参与这个线程和评论的人阅读苹果的视图控制器编程指南,并观看WWDC 2011“视图控制器控制”视频。

#1


3  

Let's consider following example based on Master-Detailed Application for iPhone only.

让我们考虑以下示例,它基于只适用于iPhone的主详细应用程序。

So, add new view controller in newly created project in Xcode: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

因此,在Xcode新创建的项目中添加新的视图控制器:

I called it NewInsideViewController. Create it without xib: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

我叫它NewInsideViewController。创建它没有xib:

Open DetailViewController.xib. Drag View Controller and View(*) objects from library to Objects area like this (I changed view's color to LightGray): iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

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

Choose this View Controller and change its Class from UIViewController to NewInsideController at the Identity Inspector: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

选择此视图控制器,并将其类从UIViewController更改为标识检查器的NewInsideController:

Assign our View(*) to NewInsideController as a view: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

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

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 ;) iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

现在IB的所有主要动作都完成了。我们需要在DetailViewController中创建NewInsideController的实例。您可以手工完成,但是Xcode有一个很好的特性—拖放;)

I called this property as myNewInsideController and DetailViewController.h looks like this:

我把这个属性叫做myNewInsideController和DetailViewController。h是这样的:

#import <UIKit/UIKit.h>
#import "NewInsideController.h"

@interface DetailViewController : UIViewController

@property (strong, nonatomic) id detailItem;
@property (strong, nonatomic) IBOutlet NewInsideController *myNewInsideController;

@property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
@end

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: iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

现在,我们的NewInsideController已经准备好工作并管理它的视图了。让我们为这个视图添加按钮和操作,以验证这一点:

Write some code in IBAction in NewInsideController.

在NewInsideController的IBAction中编写一些代码。

- (IBAction)insideButtonClick:(id)sender {
    float rPart = arc4random()%100/100.0f;
    float gPart = arc4random()%100/100.0f;    
    self.view.backgroundColor = [UIColor colorWithRed:rPart green:gPart blue:0.5f alpha:1.0f];
}

Run program.

运行程序。

#2


0  

If I understand the question clearly:

如果我清楚地了解这个问题:

  1. You have a parent view and controller, coming from a XIB.
  2. 您有一个父视图和控制器,来自一个XIB。
  3. You have placed subviews into the parent view.
  4. 您已经将子视图放置到父视图中。
  5. You're wanting each subview placed into the parent view to have it's own (custom) controller, but you don't know how to add view controller's to your hierarchy (XCode will not let you drag view controllers into a view's canvas).
  6. 您希望放置在父视图中的每个子视图都有自己的(自定义的)控制器,但是您不知道如何将视图控制器添加到层次结构中(XCode不允许将视图控制器拖放到视图的画布中)。

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:

为了简洁地回答这个问题我们假设你的项目中有一些自定义的UIViewController(每个视图控制器由。h和。m组成)请记住,如果您在父类的上下文中列出这些,它们不应该有自己的xib(您不能在IB中嵌套xib)。这里需要注意的是,您应该只在一个位置“布局”接口。如果您希望每个子视图都有XIB,那么这不是正确的方法。但是,您可以(不应该)做的是,有几个自定义的viewcontrollerde,每个自定义的viewcontrollerde连接到它位于parentView中的自己的视图,您可以将子视图控制器的outlet设置为这个parentView中的对象。哇,有点乱。另一件事你需要注意的是,你的父视图控制器需要引用每个子视图控制器为了你能够以编程方式访问这些sub-controllers和网点,对每个子视图控制器添加,你还需要添加一个IBOutlet父视图控制器指向每个subviewController:

 ParentViewController.h
 @property (nonatomic, weak) IBOutlet CustomUIViewController *firstCustomController;

And then for example to set the background color on the view of your first custom subview/controller:

然后,例如,在你的第一个自定义子视图/控制器的视图上设置背景颜色:

ParentViewController.m
[[[self firstCustomController] view] setBackgroundColor:[UIColor whiteColor]];

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.

在IB中打开父视图控制器。如果你查看可用对象的抽屉,你会发现一个通用的UIViewController对象。将它拖到父视图控制器中(不是拖到它的视图画布上,而是拖到父UIViewController对象本身中,如图ibbuilder的左列所示)。选择添加的通用视图控制器,并将其类设置为所需的UIViewController子类。现在,当您的XIB加载时,它将实例化自定义视图控制器的一个实例,以及您添加到它的画布上的内容。

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.

最后,将一个通用的UIView拖到画布上,并将其放在现有控制器的视图中(您的屏幕截图已经显示了这一点)。右键单击自定义视图控制器,将它的“视图”outlet连接到添加的视图。

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/

既然已经完成了,那么考虑一下它是否是最好的选择:嵌套视图控制器构建起来很麻烦(如您所见),而且不一定是一个好的设计决策: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.

虽然iOS5确实支持嵌套视图控制器,但我个人不会使用它们。我看重的是口述一个屏幕=一个视图控制器的最佳实践。

iOS如何添加不从源代码编码乘以viewscontroller到一个ViewController

#3


-1  

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.

视图控制器是MVC设计模式中的C部分——它们负责控制视图(及其子视图)。您不能使用控制器管理的视图,并将其作为一个不同的控制器视图的子视图——如果您这样做了,那么它就会变得很复杂,谁负责管理这个视图。

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.

尽管这种“粘贴”可能在技术上是可能的,但它会创建难以理解的代码,很难维护,而且最重要的是,它会导致bug,原因是谁负责管理视图,以及苹果的视图/控制器框架不支持这一事实。

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:

与其破坏视图控制器的层次结构,不如做以下事情:

  1. Just add subviews to your view normally, either in interface builder, or in -viewDidLoad: to add them programatically, or (rarer) override -loadView.
  2. 通常,只需在接口构建器或-viewDidLoad中向视图添加子视图:以编程方式添加它们,或者(更少)覆盖-loadView。
  3. Use view controller containment, either with Apple's ready-made ones (UINavigationController,UISplitViewController etc.) or with your own container view controllers (iOS>5).
  4. 使用视图控制器容器,要么是苹果的现成的(UINavigationController,UISplitViewController等),要么是你自己的容器视图控制器(iOS>5)。
  5. Display view controllers modally.
  6. 显示视图控制器程序地。

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.

我真的建议所有参与这个线程和评论的人阅读苹果的视图控制器编程指南,并观看WWDC 2011“视图控制器控制”视频。