iOS loadNibNamed混乱,最佳做法是什么?

Clo*_*oov 21 init uiview iboutlet ios loadnibnamed

我熟悉为我自己的UIView子类创建XIB的大部分过程,但并不是所有的东西都适合我 - 这主要与IBOutlets链接有关.我可以让它们以迂回的方式工作.

我的设置是这样的:

  • 我有MyClass.h和MyClass.m.他们有一个用于UIView的IBOutlets(称为视图)和一个UILabel(称为myLabel).我添加了'view'属性,因为在线的一些示例似乎表明你需要这个,它实际上解决了我遇到崩溃的问题,因为它无法找到view属性,我想甚至不在UIView父类中.
  • 我有一个名为MyClass.xib的XIB文件,其文件所有者自定义类是MyClass,在我的.h和.m之后正确预填充该类.

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

我尝试使用NSBundle mainBundle的'loadNibNamed'方法并将所有者设置为'self',希望我创建一个视图实例,它会自动将它的出口与我班级的出口相匹配(我知道)怎么做,我很小心).然后我想我想让'self'等于那个nib中索引0的子视图,而不是做

self = [super init];
Run Code Online (Sandbox Code Playgroud)

或类似的东西.

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

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

MyClass *instance = [[MyClass alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:instance options:nil];  
Run Code Online (Sandbox Code Playgroud)

或者像这样?

MyClass *instance = [[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:nil options:nil] objectAtIndex:0]; 
Run Code Online (Sandbox Code Playgroud)

在此先感谢您的任何帮助.

Ism*_*ael 23

第二个选项是正确的选项.你可以做的最防守的代码是这样的:

+ (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;
}
Run Code Online (Sandbox Code Playgroud)

并且这样打电话:

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
Run Code Online (Sandbox Code Playgroud)

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


Rob*_*Rob 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;
}
Run Code Online (Sandbox Code Playgroud)

所以,例如,在我的中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];
}
Run Code Online (Sandbox Code Playgroud)

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


原始答案:

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

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

// then you can do stuff like
//
// [self presentViewController:controller animated:YES completion:nil];
Run Code Online (Sandbox Code Playgroud)

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