UIView和initWithFrame以及一个NIB文件。如何获取NIB文件?


76

我有一个UIView电话baseView,在initWithFrame那儿我可以在其中添加其他一些视图并做一些自定义的事情。同一视图还具有NIB文件。

现在我有一个UIViewController名为的类AppController,我想在其中添加baseView视图到视图的AppController视图中,所以我这样做:

self.view = baseView;但是问题是没有加载NIB文件。如何确定自定义内容和NIB文件已加载/运行?

Answers:


168

您有很多选择,具体取决于将如何使用“ baseView”类并将其集成到应用程序中。目前尚不清楚您打算如何使用该类-作为UIViewController子类中的视图,还是可重复使用的模块化组件,意味着在整个应用程序中实例化多次,以用于许多不同的视图控制器。

如果您的视图是UIViewController子类中的唯一视图,那么Phonitive是正确的-将其与UIViewController子类.xib文件捆绑在一起,并使用UIViewController的viewDidLoad进行最终初始化。

但是,如果您希望View类成为在不同的View Controller中多次重用的子组件,可以通过代码集成,也可以通过包含在另一个控制器的.xib文件中进行集成,则需要同时实现initWithFrame:init方法和awakeFromNib处理这两种情况。如果内部初始化总是包含来自.xib的某些对象,则在initWithFrame中,您将需要手动加载.xib,以支持要通过代码创建窗口小部件的“客户”类。同样,如果.xib文件包含您的对象,则需要确保从awakeFromNib调用任何代码所需的终结处理。

这是一个如何使用笔尖中的UI设计创建UIView子类组件的示例。

MyView.h:

@interface MyView : UIView
{
    UIView *view;
    UILabel *l;
}
@property (nonatomic, retain) IBOutlet UIView *view;
@property (nonatomic, retain) IBOutlet UILabel *l;

MyView.m:

#import "MyView.h"
@implementation MyView
@synthesize l, view;

- (id)initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        // Initialization code.
        //
        [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil];
        [self addSubview:self.view];
    }
    return self;
}

- (void) awakeFromNib
{
    [super awakeFromNib];

    // commenters report the next line causes infinite recursion, so removing it
    // [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil];
    [self addSubview:self.view];
}

- (void) dealloc
{
     [l release];
     [view release];
     [super dealloc];
}

nib文件的外观如下所示(除了该文件的所有者需要更改为MyView类)。

在此处输入图片说明

确保将视图出口和标签出口都连接到文件所有者。而已!用于创建可重复使用的UIView小部件的模板。

关于此结构的真正好处是,您可以将MyView对象的实例放置在其他nib文件中,只需将UIView放置在所需的位置/大小,然后将身份检查器(CMD-4)中的类更改为MyView,繁荣发展,无论您想要什么视图,都可以看到小部件的实例!就像UIKit对象一样,您可以实现委托协议,以便可以将使用小部件的对象通知有趣的事件,并可以提供要显示在小部件中的数据以对其进行自定义。


1
通常,当我创建一个应用程序时,我喜欢创建一些视图,并且希望在视图控制器中使用这些视图。我不想为每个视图创建一个视图控制器,所以这就是为什么我要创建单独的视图并包含在视图控制器视图中的原因。
dbrasco'2

2
我喜欢您说我可以实现initWithFrame和awakeFromNib的事实,但是我不确定必须进行哪种初始化以及初始化的顺序。你能举个例子吗?假设我在带有IB的XIB中添加了一些标签和按钮。我的视图中有一些IBOutlets。现在我想在initWithFrame中对那些对象做一些事情。我将如何使用NIB初始化视图,以便它了解那些对象?
dbrasco'2

2
确实。当然,在几种情况下,我可以简单地将另一个VC + view推送到导航控制器上,但并非总是如此。现在,我需要重新阅读有关IBPlugins的信息:cocoawithlove.com/2009/07/…(等等,不,不是特定于iOS的,但仍然...)
Joe D'Andrea

5
awakeFromNib内部的loadNibNamed导致无限递归
Gargo 2012年

1
没错,@ Gargo是正确的,我只是测试了这段代码(很好的答案),但是在删除awaleFromNib中的loadNibNamed之后,我在初始化时进入了无限循环,此问题停止了。谢谢。
Ospho 2012年

3

我在尝试在我的应用程序中执行此操作时遇到问题后找到了该帖子。我试图在ViewDidLoad方法中从NIB实例化视图,但是控件的行为就像它们被禁用一样。我在尝试直接设置userInteractionEnabled属性并以编程方式为此视图中的按钮设置触摸事件选择器时遇到了麻烦。没事。我偶然发现了另一篇文章,发现viewDidLoad可能为时过早,无法加载此NIB。我将负载移至ViewWillAppear方法,一切正常。希望这可以帮助其他为此奋斗的人。现在,从适当的地方打电话给我,主要的回应很好,对我来说也很好。


1
请与我们分享此其他帖子的链接。

他可能会提到stackoverflow.com/a/819265/779419。实例化自定义视图时,请确保实际使用带有正确CGRect的initWithFrame。
schieferstapel 2013年

2

如果要使用NIB,最好将UIView与UIViewController链接,在这种情况下,可以使用

UIViewController *vc=[[UIViewController alloc] initWithNibName:@"YourNIBWihtOUTEXTENSION" bundle:nil]

[self.view addSubView:vc.view ];

注意内存泄漏,您必须释放vc


不对; 如果需要使用Interface Builder更改UIView的内容,则需要使用Bogatyr的方法。之所以需要将UIView与Nib结合使用,是因为Apple不鼓励使用嵌套的UIViewControllers,因为父调用可能会中断。也就是说,如果您的支持<5的iOS stackoverflow.com/questions/1141015/...
Ospho

这不是一个很好的实现-我将研究容器vcs
Adam Waite

0

如果您具有带有xib文件的自定义UIView。

- (id)initWithFrame:(CGRect)frame
{
   self = [super initWithFrame:frame];

   id mainView;
   if (self)
   {
       NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"HomeAllAdsView" owner:self options:nil];
       mainView = [subviewArray objectAtIndex:0];    
   }
   return mainView;
}

- (void) awakeFromNib
{
   [super awakeFromNib];
}

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.