23

我熟悉为我自己的 UIView 子类创建 XIB 的大部分过程,但并非一切对我来说都正常工作 - 这主要与 IBOutlets 链接有关。我可以让他们以一种迂回的方式工作。

我的设置是这样的:

  • 我有 MyClass.h 和 MyClass.m。他们有用于 UIView(称为视图)和 UILabel(称为 myLabel)的 IBOutlets。我添加了“视图”属性,因为网上的一些示例似乎表明您需要这个,它实际上解决了我因为找不到视图属性而崩溃的问题,我想即使在 UIView 父类中也没有.
  • 我有一个名为 MyClass.xib 的 XIB 文件,它的 File's Owner 自定义类是 MyClass,在该类的 .h 和 .m 存在之后正确预填充。

我的 init 方法是我遇到问题的地方。

我尝试使用 NSBundle mainBundle 的“loadNibNamed”方法并将所有者设置为“self”,希望我会创建一个视图实例,并且它会自动使其插座与我班级中的插座相匹配(我知道如何做到这一点,我很小心)。然后我想我想让'self'等于那个笔尖中索引0处的子视图,而不是做

self = [super init];

或类似的东西。

我觉得我在这里做错了,但是在线示例在 init 方法中发生了类似的事情,但是他们将该子视图 0 分配给 view 属性并将其添加为子视图-但这不是总共两个 MyClass 实例?一个基本上与 IBOutlets 无关,包含通过 loadNibNamed 实例化的子 MyClass?或者充其量,它不是一个带有额外中间 UIView 的 MyClass 实例,其中包含我最初想要作为 MyClass 的直接子级的所有 IBOutlets?当涉及到像 instanceOfMyClass.frame.size.width 这样的事情时,这会带来一点烦恼,因为它返回 0,而当引入的子 UIView 返回我正在寻找的真实帧大小时。

我做错的事情是我在 init 方法中弄乱了 loadNibNamed 吗?我应该做更多这样的事情吗?

MyClass *instance = [[MyClass alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:instance options:nil];  

还是像这样?

MyClass *instance = [[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:nil options:nil] objectAtIndex:0]; 

提前感谢您的帮助。

4

3 回答 3

24

第二个选项是正确的。你可以做的最具防御性的代码是这样的:

+ (id)loadNibNamed:(NSString *)nibName ofClass:(Class)objClass {
    if (nibName && objClass) {
        NSArray *objects = [[NSBundle mainBundle] loadNibNamed:nibName 
                                                         owner:nil 
                                                       options:nil];            
        for (id currentObject in objects ){
            if ([currentObject isKindOfClass:objClass])
                return currentObject;
        }
    }

    return nil;
}

并像这样调用:

MyClass *myClassInstance = [Utility loadNibNamed:@"the_nib_name" 
                                         ofClass:[MyClass class]]; 
// In my case, the code is in a Utility class, you should 
// put it wherever it fits best

我假设您的 MyClass 是UIView? 如果是这种情况,那么您需要确保UIView.xib 实际上是 MyClass 类。选择视图后,在界面构建器右侧的第三个选项卡上定义

于 2012-11-23T19:13:35.497 回答
7

您需要做的就是通过创建子视图loadNibNamed,设置框架并将其添加到子视图中。例如,我正在使用我MyView的类添加三个子视图,这是一个UIView子类,其接口在 NIB 中定义,MyView.xib

所以,我initWithFrame为我的UIView子类定义:

- (id)initWithFrame:(CGRect)frame
{
    NSLog(@"%s", __FUNCTION__);

    self = [super initWithFrame:frame];
    if (self)
    {
        NSArray *nibContents = 
          [[NSBundle mainBundle] loadNibNamed:@"MyView" 
                                        owner:self 
                                      options:nil];
        [self addSubview:nibContents[0]];
    }
    return self;
}

因此,例如,在 my 中UIViewController,我可以像这样加载几个这样的子类UIView对象:

for (NSInteger i = 0; i < 3; i++)
{
    CGRect frame = CGRectMake(0.0, i * 100.0 + 75.0, 320.0, 100.0);
    MyView *myView = [[MyView alloc] initWithFrame:frame];
    [self.view addSubview:myView];

    // if you want, do something with it: 
    // Here I'm initializing a text field and label

    myView.textField.text = [NSString stringWithFormat:@"MyView textfield #%d",
                              i + 1];
    myView.label.text = [NSString stringWithFormat:@"MyView label #%d", 
                          i + 1];
}

我最初建议使用控制器,我将在下面保留该答案以供历史参考。


原答案:

我在这里看不到任何对视图控制器的引用。通常你会有一个 的子类 UIViewController,然后你会用它来实例化

MyClassViewController *controller = 
  [[MyClassViewController alloc] initWithNibName:@"MyClass" 
                                          bundle:nil];

// then you can do stuff like
//
// [self presentViewController:controller animated:YES completion:nil];

如果需要,NIB 文件MyClass.xib可以指定 的基类UIView,您可以在其中拥有所有与视图相关的代码(例如,假设 MyClass 是 的子类UIView)。

于 2012-11-23T19:14:00.103 回答
2

这是我使用的一种方法:

  1. 为 创建一个子类UIView,这将被调用MyClass
  2. 创建一个视图 xib 文件。在界面生成器中打开,单击文件的所有者,然后在身份检查器中,将类更改为父视图控制器的类,例如 ParentViewController.
  3. 单击对象列表中已有的视图并将其在 Identity Inspector 中的类更改为MyClass
  4. 您声明的任何出口/操作MyClass都将通过从视图(不是文件的所有者)单击拖动来连接。如果要将它们连接到变量,ParentViewController请从文件所有者单击拖动。
  5. 现在,您ParentViewController需要为MyClass.

ParentViewController.h添加以下内容:

@class MyClass

@interface ParentViewController : UIViewController {
    MyClass *myClass;
}

@property (strong, nonatomic) MyClass *myClass;

在您的实现中综合它并在您的 viewDidLoad方法中添加以下内容:

- (void)viewDidLoad {
    [super viewDidLoad];

    [[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:self options:nil];
    self.myClass.frame = CGRectMake(X,Y,W,H); //put your values in.
    [self.view addSubview:self.myClass];
}
于 2012-11-23T20:36:02.260 回答