iOS loadNibNamed confusion, what is best practice?

前端 未结 3 1276
野的像风
野的像风 2020-12-14 02:08

I\'m familiar with most of the process of creating an XIB for my own UIView subclass, but not everything is working properly for me - it\'s mostly to do with the IBOutlets l

相关标签:
3条回答
  • 2020-12-14 02:45

    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

    0 讨论(0)
  • 2020-12-14 03:01

    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];
    }
    
    0 讨论(0)
  • 2020-12-14 03:07

    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).

    0 讨论(0)
提交回复
热议问题