62

I've created a view in a xib (with an activity indicator, a progress view and a label). Then I've created .h/.m files:

#import <UIKit/UIKit.h>

@interface MyCustomView : UIView {
    IBOutlet UIActivityIndicatorView *actIndicator;
    IBOutlet UIProgressView *progressBar;
    IBOutlet UILabel *statusMsg;
}

@end

#import "MyCustomView.h"

@implementation MyCustomView    

- (id)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
        // Initialization code
    }
    return self;
}

- (void)dealloc {
    [super dealloc];
}

@end

In IB, I set the file's owner and view identity to MyCustomView and connect the IBOutlet to the File's owner

In MyViewController.m, I've:

- (void)viewDidLoad {

    [super viewDidLoad];   

    UIView *subView = [[MyCustomView alloc] initWithFrame:myTableView.frame];
    [subView setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5]];

    [myTableView addSubview:subView];
    [subView release];
}

When I run the app, the view is added, but I can't see the label, the progress bar and the activity indicator.

What am I doing wrong?

Pierre de LESPINAY
  • 44,700
  • 57
  • 210
  • 307
Sefran2
  • 3,578
  • 13
  • 71
  • 106

3 Answers3

131

You need to load it using the -loadNibNamed method. -initWithNibName is only for UIViewControllers.

Add the following code to your MyCustomView init method:

NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"MyCustomView" owner:self options:nil];
UIView *mainView = [subviewArray objectAtIndex:0];
[self addSubview:mainView];

Remember, if you are initializing an object from a nib, it calls - (id)initWithCoder:(NSCoder *)aDecoder to initialize, so you'll have to override that if you are creating the MyCustomView object within the nib. If you're just doing it with initWithFrame:, then just override that and add the code above. Also, in your nib, make sure you have one top-level UIView, and place all other elements within that (that makes sure that your subviewArray only has one entry).

This will load the views from the nib and add them to the object, and should do the trick.

Ned
  • 6,280
  • 2
  • 30
  • 34
  • I used your code in the initWithFrame and now I can see the MyCustomView with all its elements, but there is one thing that doesn't work. In the viewDidLoad of MyViewController I've: UIView *subView = [[MyCustomView alloc] initWithFrame:myTableView.frame]; [subView setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5]]; [myTableView addSubview:subView]; [subView release]; so that I should see the table under it. Any ideas? – Sefran2 Mar 18 '11 at 21:06
  • It works, if I set it in the initWithFrame. Now I've to understand how support the landscape mode for this view :) Thanks – Sefran2 Mar 18 '11 at 21:13
  • I've found another solution that resolves also the landscape problem. I use the loadNibNamed code in MyViewController (when I have to display the subview) and I put any other customization in the awakeFromNib method in MyCustomView.m – Sefran2 Mar 19 '11 at 10:38
  • Hey, the method [self addSubview:mainView] only adds the view you made in IB to the MyCustomView. I tried your method and then tried to set the frame for MyCustomView. Turns out that the frame changes but the frame of the view made in .xib does not change. How do i change the frame of the IB view through MyCustomView? – HG's Apr 08 '11 at 09:07
  • Just do mainView.frame = newFrame. So, if you want the IB view's frame to take up the entire MyCustomView frame, do "mainView.frame = self.bounds". – Ned Apr 09 '11 at 12:53
  • @Ned thanks for the tip on `initWithCoder:`. I couldn't figure out how my custom view was getting created without `init` or `initWithFrame` being called. – Christopher Pickslay Oct 27 '11 at 23:01
  • The very important thing I want to point out here: in xib file, in File's owner, change to our custom view class name, NOT the View item. – felixwcf Nov 15 '16 at 09:26
1

I think you need to use this method:

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

This is because you need to pass it the .xib filename in the "nibNameOrNil".

hocker
  • 688
  • 6
  • 18
  • Shouldn't be enough specifying in IB the identity of the file's owner and view as MyCustomView? – Sefran2 Mar 18 '11 at 16:25
  • If I use initWithNibName, I obtain the warning: 'UIView' may not respond to '-initWithNibName:bundle:' – Sefran2 Mar 18 '11 at 17:45
0

As hocker said you have to use that method passing in the XIB name (without the extension).

Then you have to control this list:

  • Open the .xib file in IB
  • Click on File Owner and select the correct class (MyCustomView in your case)
  • Hold down control and drag from File Owner to the View (Now the outlet for the view is ok)

Hope it works. Cheers.

Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
  • Nothing. If the File Owner is MyCustomView, I can't drag from File Owner to the View. So I've set the File Owner to MyViewController and the View to MyCustomView, and drag from the View to the IBOutlets, but it doesn't work. – Sefran2 Mar 18 '11 at 20:49