iOS loadNibNamed confusion, what is best practice?

六月ゝ 毕业季﹏ 提交于 2019-11-28 20:27:14
Ismael

The second option is the correct one. The most defensive code you could do is like this:

+ (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;
}

And call like this:

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

I'm assuming your MyClass is a subclass of UIView? If that's the case, then you need to make sure that the UIView of your .xib is actually of MyClass class. That is defined on the third Tab on the right-part in the interface builder, after you select the view

Rob

All you need to do is create the subview via loadNibNamed, set the frame, and add it to the subview. For example, I'm adding three subviews using my MyView class, which is a UIView subclass whose interface is defined in a NIB, MyView.xib:

So, I define initWithFrame for my UIView subclass:

- (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;
}

So, for example, in my UIViewController, I can load a couple of these subclassed UIView objects like so:

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];
}

I originally advised the use controllers, and I'll keep that answer below for historical reference.


Original answer:

I don't see any references to view controllers here. Usually you'd have a subclass of UIViewController, which you would then instantiate with

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

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

The NIB file, MyClass.xib, could specify that the base class for the UIView, if you want, where you have all of the view related code (e.g. assuming that MyClass was a subclass of UIView).

Here's one method that I use:

  1. Create a subclass for UIView, this will be called MyClass
  2. Create a view xib file. Open in interface builder, click File's Owner and in the Identity Inspector, change the class to that of your parent view controller, e.g. ParentViewController.
  3. Click the view already in the list of objects and change it's class in Identity Inspector to MyClass.
  4. Any outlets/actions that you declare in MyClass will be connected by click-dragging from View (not File's Owner). If you want to connect them to variables from ParentViewController then click-drag from File's Owner.
  5. Now in your ParentViewController you need to declare an instance variable for MyClass.

ParentViewController.h add the following:

@class MyClass

@interface ParentViewController : UIViewController {
    MyClass *myClass;
}

@property (strong, nonatomic) MyClass *myClass;

Synthesize this in your implementation and add the following in your viewDidLoad method:

- (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];
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!