【问题标题】:Interface-Builder: "combine" NSView-class with .xibInterface-Builder:将 NSView 类与 .xib “组合”
【发布时间】:2013-08-23 14:35:38
【问题描述】:

我想在 Interface-Builder 中设置一个自定义 NSView,但我无法让它在 OSX 上工作。

在我的 ViewController 的 .xib 中,我添加了一个自定义视图并将 Class 设置为 MyCustomView。我创建了 MyCustomView.h、MyCustomView.m 和 MyCustomView.xib。

在 MyCustomView.xib 中,我也将 Class 设置为 MyCustomView。在 MyCustomView.m 中,- (void)awakeFromNib 被调用,但 - (id)initWithCoder:(NSCoder *)aDecoder- (id) awakeAfterUsingCoder:(NSCoder*)aDecoder 没有被调用。

我想要实现的是,在我的 ViewController 中,我添加的视图被我在 MyCustomView.xib 中设置的视图“填充”。最好的方法是什么?

编辑:我认为我不够清楚......

我的 ViewController 包含一个名为 MyCustomView 的自定义视图。

这个视图应该是 MyCustomView 类型,其中

MyCustomView.h 我的自定义视图.m MyCustomView.xib

存在。我已经将 MyCustomView.xib 的 File's Owner 设置为 MyCustomView,并且我已经将 ViewController 中的 CustomView 设置为 MyCustomView - 但它不起作用。

如果我这样做

- (void)awakeFromNib {
    NSString* nibName = NSStringFromClass([self class]);
    NSArray* topLevelObjects;
    [[NSBundle mainBundle] loadNibNamed:nibName
                              owner:nil
                    topLevelObjects:&topLevelObjects];

    NSView* view = topLevelObjects[0];
    [view setFrame:[self bounds]];
    [self addSubview:view];
}

我只得到一个 NSView 类型的视图,而不是 MyCustomView...有没有简单的方法告诉 ViewController.xib 它是一个 MyCustomView?

编辑 2:我上传了一个简单的项目

https://dl.dropboxusercontent.com/u/119600/Testproject.zip,您会发现一个带有 MyCustomView 的简单项目(不是在 ViewController 中,而是在 window.xib 中) - 但它没有显示 MyCustomView.xib 中的按钮。我想实现这一点 - 最简单、最好的方法是什么?

【问题讨论】:

  • 你想完成什么?这是一套标准控件,您需要使用的地方很多吗?视图的各个部分是否需要触发或需要从ViewController 访问的出口?视图类真的更像是一个子视图控制器吗?另外,上面列出的-awakeFromNib 代码在哪里(MyCustomClassViewController)?
  • 请看我上传的项目,应该会更清楚。 awakeFromNibMyCustomClass 中。

标签: macos interface-builder


【解决方案1】:

编辑 - 抱歉,我现有的答案没有考虑到连接插座和操作的需要。这种方式应该可以做到……

鉴于文件...

MyCustomView.h
MyCustomView.m
MyCustomView.xib

在 MyCustomView.h 中

  • 为您的界面元素声明 IBOutlets。您至少需要一个,来保存指向 xib 文件中顶级视图的指针

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

在 MyCustomView.xib 中

  • 确保只有一个顶级视图
  • 在身份检查器中将文件的所有者类设置为 MyCustomView
  • 确保将顶级视图设置为默认的NSView 类。
  • 现在您可以将 MyCustomView.h 中声明的 IBOutlets 连接到 xib 文件中的接口对象。至少您需要将顶层视图连接到您的view 插座。

在 MyCustomView.m 中:

- (id)initWithFrame:(NSRect)frame
{
    NSString* nibName = NSStringFromClass([self class]);
    self = [super initWithFrame:frame];
    if (self) {
        if ([[NSBundle mainBundle] loadNibNamed:nibName 
                                          owner:self 
                                topLevelObjects:nil]) {
            [self.view setFrame:[self bounds]];
            [self addSubview:self.view];
            [self.myCustomButton setTitle:@"test success"];
        }
    }
    return self;
}

在窗口的 xib 文件中,添加自定义 NSView 并将其类更改为 MyCustomView。

在 10.8 之前的 OSX 中,方法 loadNibNamed 是一个类方法 - 如果您需要向后兼容,请改用它,但现在已弃用:

[NSBundle loadNibNamed:@"NibView" owner:self]

请注意,MyCustomView.xib 的视图不是 MyCustomView 的视图,而是它的视图的唯一子视图(这类似于 tableViewCell 拥有单个 contentView 的方式)。

在您发布的项目示例中,您需要进行以下更改:

  • 在 MyCustomView.h
    .添加一个 NSView 属性

  • 在 MyCustomView.xib 中:
    .将顶级视图从 MyCustomView 自定义类更改为 NSView(默认)
    .将文件的所有者设置为 MyCustomView
    .将文件所有者的 viewmyCustomButton 的 IBOutlets 连接到界面视图和按钮
    .为了测试,将视图缩小很多并将按钮向上推到右上角(您不会在窗口中看到它,因为它在这里)

  • 在 MyCustomView.m 中:
    .在这里用initWithFrame方法替换你所有的实现代码

【讨论】:

  • 现在看起来好多了,但是按钮的标题没有设置为“测试成功”;这对你有用吗?
  • @swalkner,我已经(再次)对你的项目进行了测试,它可以工作。您是否将 File 所有者中的 view 和 myCustomButton IBOutlets 重新连接到 Xib 按钮?
  • 它有效,非常感谢 - 我将它连接到自定义视图,而不是文件的所有者。现在我正在解决类似的问题(在 IB 中添加 ViewController 的视图),但我想这是一个新问题......谢谢!
  • @foundry 我会认为像上面这样的事情会更简单,因为它需要更频繁地完成?如上所述,它几乎感觉就像你在违背谷物来完成它。 Cocoa 中使用了哪些其他模式来实现类似的结果?
【解决方案2】:

为了加载视图或控件的自定义子类(或任何其他可在 Interface Builder 中使用的类),您需要添加基本版本(在您的情况下为 NSView,并且您有完成),然后在窗口中选择该对象并转到身份检查器(Cmd-Opt 3)。

输入自定义子类的名称,而不是类的预定义值(在您的情况下为 NSView)。瞧!

与 IB UX 相关的一个小细节是,您可能必须将焦点从输入字段移开,以便在构建和运行应用程序时注册该更改。

【讨论】:

  • 我做了,但是不行,请以我上传的项目为例。
猜你喜欢
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
相关资源
最近更新 更多