如何使用 IB_DESIGNABLE 在故事板中可视化可重用的 xib?

How to visualize reusable xibs in storyboards using IB_DESIGNABLE?

我想在故事板中使用 Xcode 9.2 中的 IB_DESIGNABLE 常量和 Objective C 目标 iOS SDK 11.2 来可视化 XIB。

根据 Apple 的 this articleprepareForInterfaceBuilder 方法由 Interface Builder 调用,让您可以做任何只能为 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.

基于此 article 我想在故事板中可视化 XIB。当我在 ViewController 上使用 UIView 元素并设置

我收到以下构建时错误:

Main.storyboard:
error: IB Designables: 
Failed to render and update auto layout status for MainViewController (8zi-kg-fjR):
The agent threw an exception.

我在 Main.storyboard 中使用的视图中收到此错误而不是可视化 XIB,我做错了什么?

这是XibView.h

IB_DESIGNABLE
@interface XibView : UIView
@property (nonatomic, strong) IBOutlet UIView* contentView;
@property (nonatomic) IBInspectable NSString* nibName;
@end

这是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

这是我认为有错误的方法:

- (void)xibSetup
{
    [[NSBundle mainBundle] loadNibNamed:_nibName owner:nil options:nil];
    [self addSubview:self.contentView];
    self.contentView.frame = self.bounds;
}

nib 加载程序无法设置 self.contentView,因为您没有将 self 作为 owner 参数传递给 loadNibNamed:options:。试试这个:

    [[NSBundle mainBundle] loadNibNamed:_nibName owner:self options:nil];

@E.Coms and still based on this article 的帮助下,我弄清楚了问题所在。要在此处提供供其他人使用的答案,您可以找到步骤

如何使用 IB_DESIGNABLE 和 Objective-C 在故事板中可视化可重复使用的 xibs?

  1. 创建 Xib 持有者 objective-c header 和 class 文件 (XibViewHolder)
  2. 创建 Xib 文件(MyView.xib)
  3. 将 Xib 的“文件所有者”class 设置为 XibViewHolder
  4. 在任何视图控制器的故事板上添加一个 UIView
  5. UIView 的 class 设置为 XibViewHolder class
  6. UIView 的 Interface Builder 属性 调用 Nib Name 设置为您要加载的 Xib 的名称,例如: MyView.

这是XibViewHolder.h

IB_DESIGNABLE
@interface XibViewHolder : UIView
@property (nonatomic, strong) UIView* contentView;
@property (nonatomic, strong) IBInspectable NSString* nibName;
@end

这是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