Nibs are great. They reduce the drudgery of view layout and allow us to work at a level of abstraction that matches the problem domain. But things aren’t all rosy. There are aspects of the implementation that leave room for improvement. The most common usage of nibs (in iOS at least) is to setup the view for a UIViewController. Some times, however, we want to re-use a specific subview between these nibs but it’s not obvious how best to do this. Here’s how to load a view from a nib so that the view can be instantiated in code and from other nibs.
Create a UIView sub class and a nib file:
@interface BCDemoView ()
@property(nonatomic) IBOutlet UIImageView *imageView;
@property(nonatomic) IBOutlet UILabel *titleLabel;
@property(nonatomic) IBOutlet UILabel *subtitleLabel;
@end
@interface BCDemoView ()
@property(nonatomic) IBOutlet UIImageView *imageView;
@property(nonatomic) IBOutlet UILabel *titleLabel;
@property(nonatomic) IBOutlet UILabel *subtitleLabel;
@property(nonatomic) IBOutlet UIView *container;
@end
@interface BCDemoView : UIView
@property(nonatomic, readonly) UIImageView *imageView;
@property(nonatomic, readonly) UILabel *titleLabel;
@property(nonatomic, readonly) UILabel *subtitleLabel;
@end
the file owner is an instance of your class:
the base UIView is connected to the container property of the file owner:
the remaining outlets are connected to subviews of the container view:
@implementation BCDemoView
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self == nil) return nil;
[self initalizeSubviews];
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self == nil) return nil;
[self initalizeSubviews];
return self;
}
-(void)initalizeSubviews
{
//Load the contents of the nib
NSString *nibName = NSStringFromClass([self class]);
UINib *nib = [UINib nibWithNibName:nibName bundle:nil];
[nib instantiateWithOwner:self options:nil];
//Add the view loaded from the nib into self.
[self addSubview:self.container];
}
@end