使用Interface Builder创建的自定义视图在其他视图中调用时不会呈现 [英] Custom view created with Interface Builder does not render when called in other views

查看:137
本文介绍了使用Interface Builder创建的自定义视图在其他视图中调用时不会呈现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个主窗口的xib,我按以下步骤创建了一个自定义视图:

I have an xib for the main window, and I created a custom view in the following steps:


  1. 创建一个新类继承自 NSView

  1. Create a new class which inherits from NSView.

MyView.h

    #import <Cocoa/Cocoa.h>
    IB_DESIGNABLE
    @interface MyView : NSTableCellView
    @end

MyView.m

    #import "MyView.h"

    @implementation MyView

    - (void)awakeFromNib {
        NSLog(@"Post view awaking from nib.");
    }

    @end




  1. 创建一个新的xib,并将根视图的类设置为上面创建的类。并设计在xib中。

  2. 设置从xib到类的出口。

和我尝试在主窗口中使用此自定义视图执行以下步骤:

And I tried to use this custom view in the main window in the following steps:


  1. 将自定义视图拖动到主窗口的xib。

  2. 将该自定义视图的类设置为上面创建的类。

但没有任何渲染。从日志中,我可以看到自定义视图类中的 awakeFromNib 中的代码被执行。当我将类设置为 IB_DESIGNABLE 时,视图在主窗口的xib中变空,与我设计的不同。

But nothing renders. From the log, I can see that code in awakeFromNib from the custom view class is executed. When I set the class to be IB_DESIGNABLE, the view gets empty in the main window's xib, different from what I designed.

我尝试将自定义视图的xib的文件所有者设置为自定义类,但没有任何更改。

I tried to set the file owner of the custom view's xib to the custom class, but nothing changed.

我想问题是,自定义视图的xib文件实际上没有加载。当我用谷歌搜索它时,似乎很少有关于这个确切主题的参考文献。那么,我该如何实现这一目标呢?即,在IB中设计一个视图,在类中实现它的方法,关联这两个,并将其公开,就像系统视图一样用于其他xib?

I guess the problem is that, the custom view's xib file is not actually loaded. When I googled it, there seem to be few references on this exact topic. So, how should I actually achieve this goal? I.e., design a view in IB, implement its methods in a class, associate these two, and expose it just like a system view for use in other xibs?

更新:

我找到了一个教程,并意识到我缺少的东西(在构建时正确渲染视图)。我必须在xib视图中添加一个插座到视图类:

I found a tutorial and realized what I lack (for correctly rendering the view when built). I have to add an outlet from the view in the xib to the view class:

@property (nonatomic, strong) IBOutlet NSView *view;

,然后将其加载到(id)initWithCoder中:( NSCoder * )编码器方法。

, and then load it in the (id)initWithCoder:(NSCoder *)coder method.

[[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self topLevelObjects:nil];
[self addSubview:self.view];

但视图仍然无法在界面构建器中呈现。

But the view still won't render in the interface builder.

推荐答案

您的猜测是正确的:未加载xib。 nib加载器不知道您的自定义视图的笔尖。 nib框架不提供定义该连接的工具,因此您需要编写代码来加载xib。

Your guess is correct: the xib is not being loaded. The nib loader doesn't know about your custom view's nib. The nib framework doesn't provide a facility for defining that connection, so you need to write code to load the xib.

这就是我要做的。将 contentView 属性添加到自定义视图中:

Here's what I'd do. Add a contentView property to your custom view:

@interface MyView ()

@property (nonatomic, strong, readwrite) IBOutlet NSView *contentView;

@end

在自定义视图的笔尖中,设置自定义类根视图返回 NSView 并断开所有(不再有效)插座连接。将文件所有者的自定义类设置为您的自定义类名(例如 MyView )。将根视图连接到文件所有者的 contentView 插座,并将文件所有者的所有其他插座连接到笔尖中的相应对象。

In your custom view's nib, set the custom class of the root view back to NSView and disconnect all the (no-longer-valid) outlet connections from it. Set the custom class of File's Owner to your custom class name (e.g. MyView). Connect the root view to File's Owner's contentView outlet, and connect all the other outlets from File's Owner to the appropriate objects in the nib.

然后在自定义视图子类中实现 awakeFromNib 以加载nib并将内容视图添加为子视图:

Then implement awakeFromNib in your custom view subclass to load the nib and add the content view as a subview:

@implementation MyView {
    BOOL hasLoadedOwnNib: 1;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    [self loadOwnNibIfNeeded];
}

- (void)loadOwnNibIfNeeded {
    if (hasLoadedOwnNib) {
        return;
    }

    hasLoadedOwnNib = YES;

    [[NSBundle bundleForClass:self.class] loadNibNamed:NSStringFromClass(self.class) owner:self topLevelObjects:nil];
    self.contentView.frame = self.bounds;
    self.contentView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
    [self addSubview:self.contentView];
}

@end

请注意,你必须是注意不要允许无限递归。当你的应用加载主窗口的笔尖时,它会创建一个 MyView 的实例,并且(最终)发送它 awakeFromNib 。然后,在 awakeFromNib 中, MyView 加载自己的nib,它是文件的所有者。 nib加载器将 awakeFromNib 发送给文件所有者,当你已经在 - [MyView awakeFromNib] 时会发生这种情况。如果不检查这一点,由于无限递归,会出现堆栈溢出。

Note that you have to be careful not to allow infinite recursion. When your app loads the main window's nib, it will create an instance of MyView and (eventually) send it awakeFromNib. Then, in awakeFromNib, MyView loads its own nib, where it is the File's Owner. The nib loader sends awakeFromNib to File's Owner, and this will happen while you're already in -[MyView awakeFromNib]. If you don't check for this, you get a stack overflow due to unbounded recursion.

这篇关于使用Interface Builder创建的自定义视图在其他视图中调用时不会呈现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆