I want to visualize XIB's in a storyboard using the IB_DESIGNABLE constant in Xcode 9.2 with Objective C targeting iOS SDK 11.2.
According this article from Apple the prepareForInterfaceBuilder
method is called by the Interface Builder to let you do whatever shall only be done for the Interface Builder.
When Interface Builder instantiates a class with the IB_DESIGNABLE attribute, it calls this method to let the resulting object know that it was created at design time. You can implement this method in your designable classes and use it to configure their design-time appearance.
Based on this article I want to visualize XIB's in my storyboard. When I use a UIView
element on a ViewController and set
XibView
nibName
property to MainViewController
, the name of the XIB fileI get the following buildtime error:
Main.storyboard:
error: IB Designables:
Failed to render and update auto layout status for MainViewController (8zi-kg-fjR):
The agent threw an exception.
What am I doing wrong that I get this error instead the visualized XIB in the View I use in the Main.storyboard?
This is the XibView.h
IB_DESIGNABLE
@interface XibView : UIView
@property (nonatomic, strong) IBOutlet UIView* contentView;
@property (nonatomic) IBInspectable NSString* nibName;
@end
This is the XibView.m
#import "XibView.h"
@implementation XibView
- (id)initWithCoder:(NSCoder *) coder
{
self = [super initWithCoder: coder];
if (self)
{
[self xibSetup];
}
return self;
}
//---------------------------------------------------------------------
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self xibSetup];
}
return self;
}
//---------------------------------------------------------------------
- (void)prepareForInterfaceBuilder
{
[super prepareForInterfaceBuilder];
[self xibSetup];
}
//---------------------------------------------------------------------
- (void)xibSetup
{
[[NSBundle mainBundle] loadNibNamed:_nibName owner:nil options:nil];
[self addSubview:self.contentView];
self.contentView.frame = self.bounds;
}
@end
With the help of @E.Coms and still based on this article I figured it out what the problem was. To deliver an answer to be used for others here you can find the steps
How to visualize reusable xibs in storyboards using IB_DESIGNABLE with Objective-C?
XibViewHolder
)MyView.xib
)XibViewHolder
UIView
UIView
's class to XibViewHolder
classUIView
's Interface Builder property called Nib Name, which is defined in the Xib holder class, to the name of the Xib you want to load e.g.: MyView
.This is the XibViewHolder.h
IB_DESIGNABLE
@interface XibViewHolder : UIView
@property (nonatomic, strong) UIView* contentView;
@property (nonatomic, strong) IBInspectable NSString* nibName;
@end
This is the XibViewHolder.m
#import "XibViewHolder.h"
@implementation XibViewHolder
- (void)awakeFromNib
{
[super awakeFromNib];
[self xibSetup];
}
- (void)prepareForInterfaceBuilder
{
[super prepareForInterfaceBuilder];
[self xibSetup];
[self.contentView prepareForInterfaceBuilder];
}
- (void)xibSetup
{
if (_nibName == nil) { return; }
UIView* loadedNibView = [self loadViewFromNib];
loadedNibView.frame = self.bounds;
loadedNibView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
[self addSubview:loadedNibView];
self.contentView = loadedNibView;
}
- (UIView*)loadViewFromNib
{
NSBundle* bundle = [NSBundle bundleForClass:[self class]];
UINib* nib = [UINib nibWithNibName:_nibName bundle:bundle];
return [nib instantiateWithOwner:self options:nil].firstObject;
}
@end