使用Interface Builder创建的自定义视图在其他视图中调用时不会呈现 [英] Custom view created with Interface Builder does not render when called in other views
问题描述
我有一个主窗口的xib,我按以下步骤创建了一个自定义视图:
I have an xib for the main window, and I created a custom view in the following steps:
- 创建一个新类继承自
NSView
。
- 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
- 创建一个新的xib,并将根视图的类设置为上面创建的类。并设计在xib中。
- 设置从xib到类的出口。
和我尝试在主窗口中使用此自定义视图执行以下步骤:
And I tried to use this custom view in the main window in the following steps:
- 将自定义视图拖动到主窗口的xib。
- 将该自定义视图的类设置为上面创建的类。
但没有任何渲染。从日志中,我可以看到自定义视图类中的 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屋!