0
votes

how to I introduce use of a NIB file to my existing custom UIView? For example:

a) should the NIB load automatically somehow if named the name as the *.h & *.m file? (i.e. I'm talking about a custom UIView here, not a UIControllerView)

b) if you have to do it manually do you need to use "[[NSBundle mainBundle] loadNibNamed:@"NIBfilename" owner:self options:nil];" perhaps?

c) if yes (to b above), then in whether method do you do this, in the custom view's "- (id)initWithCoder:(NSCoder *)coder" method?

PS. For use in discussion with @Katfish's answer. Katfish, when I put the "NSArray *nibs = [[NSBundle mainBundle]..." line in I get a recursive loop of hits to "initWithCoder"? [PS see comment I just made to @sergio's answer, which might explain this?]

// Code within my custom UIView
- (id)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:@"ClockView" owner:self options:nil];
        self = [nibs objectAtIndex:0];
        .
        .
        .
    }
    return self;
}

PSS. Noting that status of where I'm up to here (see comments in Sergio's answer) I am now wondering whether what I'm doing is possible at all? Based on seeing Custom UIView from Interface Builder . Perhaps I could create a custom UIView but only ever use via creating/instantiating it programmatically from the UIControllerView I'm calling it from?

4

4 Answers

1
votes

a) should the NIB load automatically somehow if named the name as the *.h & *.m file? (i.e. I'm talking about a custom UIView here, not a UIControllerView)

As far as I know, nibs are not loaded automatically, except for MainWindow, which is loaded by UIKit according to what it specified in info.plist;

b) if you have to do it manually do you need to use "[[NSBundle mainBundle] loadNibNamed:@"NIBfilename" owner:self options:nil];" perhaps?

loadNibNamed is a good option if you do not want to instantiate a view controller and need just an array of the top object you defined in your nib;

c) if yes (to b above), then in whether method do you do this, in the custom view's "- (id)initWithCoder:(NSCoder *)coder" method?

I would use initWithCoder if you are loading the base view from a nib, initWithFrame if you create it programmatically.

EDIT:

As to your PS, I guess that you set one of the object in your xib file to be an instance of the UIView subclass where you define initWithCoder. (e.g., if your UIView subclass is MyView, then you also instantiated a view object in the xib and set its class to MyView).

If this is the case, what you need to do is define the File's Owner to the concrete derived UIView class (e.g., MyView); indeed you are already instantiating the UIView derived class and when loading the nib you only need specifying the file's owner (through the owner argument).

EDIT 2:

oh actually I see that in fact I have (a) in the parent UIControllerView which uses my custom view, in IB for it's XIB I use a UIView which I've set the classname to "clockview", but then (b) in my actual clockview custom UIView (not UIControllerView) XIB file I've done the same thing and set the class name to be "clockview". Do you know what classname I should be using for (a) parent UIControllerView and (b) the custom UIView itself here? (getting a bit confused) – Greg 1 hour ago

After reading your comment, you have two ways of doing it.:

First Option

  1. in your UIViewController related xib, you are doing right;

  2. in your other xib file, remove the custom UIView (the one you assigned the class name clockview; this object will be already created by the xib of point 1, so you don't need to instantiate it again); select the File's Owner of this "other xib" and set its class name to clockwork.

In this case, you would define initWithCoder as you did previously. Drawback of this is that you instantiate objects in one nib and the view in the other; you won't be able to define the clockview view in the second nib. So,...

Second Option

  1. in your UIViewController related xib, change the UIView class name and set it to UIView; this view will be thus a "normal" view that you will use as an empty view to host the other view from the second xib file;

  2. in your other xib file, leave things as they are; possibly you could set the File's Owner in this case to the UIViewController of point 1.

I think that this second case is the one that you are aiming at. In this case, you don't need to do anything specific in your clockview's initWithCoder; what you need is, in your UIViewController, load the xib view when appropriate; typically this could be in viewDidLoad (or elsewhere, possibly after you click on a button, it depends on your app):

 - (void)viewDidLoad {
     [super viewDidLoad];
     NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:@"ClockView" owner:self options:nil];
     for (NSObject *obj in nibs) {
        if ( [obj isKindOfClass:[clockview class]]) {
            [self addSubview:(clockview*)obj];
            break;
        }
     }
  }

What I am doing in this viewDidLoad is identifying the clockwork view that is instantiated by loading the second xib file; and adding it to the controller's view as a subview.

Again, observe the controller argument that I passed to loadNibNamed; this must correspond to the object you specified as file's owner of the second xib.

I think that it should work in this way.

0
votes

You can assign a nib to a UIView in - (id)init.

- (id)init {

    NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:@"NIBfilename" owner:self options:nil];
    self = [nibs objectAtIndex:0];
    [self retain];

    return self;

}
0
votes

a) If you have a NIB file, and the owner is the .h file, then when the header file, a UIViewContoller subclass is loaded with the [alloc] initWithNibName, then the NIB is loaded automatically.

b) YES

c) you can use the initWithNibName method.

Do you want to add a component from a .xib file to your existing UIView which is loaded already by the view controller?

Then you can load the .xib component in this way, and then get the component from the array.

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {


    // open xib and find tableView
    if ( (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) ) {
        NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:nibNameOrNil owner:self options:nil];

        for (NSObject *obj in nibs) {
            if ( [obj isKindOfClass:[UITableView class]]) {
                self.tableContent = (UITableView *) obj;
            }
        }
        self.view = self.tableContent;              

        [self initializeDefaultValues];     
    }

    return self;
}
0
votes

In general, Write a class yourController which is inherited from NSObject and set the file owner of the nib to yourController class. And in yourController class handle nib loading([[NSBundle mainBundle] loadNibNamed:@"NIBfilename" owner:self options:nil]).
And if you want to initialize some data to the view which is loaded from the nib use initWithCoder method.