【问题标题】:Interface Builder: How to load view from nib fileInterface Builder:如何从 nib 文件加载视图
【发布时间】:2013-10-31 07:08:52
【问题描述】:

我有一个从 NSView 子类化的 MyCustomView,在 .xib 中设计。

我想将此视图插入到我的其他一些 xib 的应用程序中。我该怎么做?如果我拖动自定义视图并将类更改为 MyCustomView,但这不会加载我的 xib 文件。这只能以编程方式完成,还是有办法在界面构建器中做到这一点?

EDIT1:

这是一个非常小的演示项目: http://s000.tinyupload.com/index.php?file_id=09538344018446482999

它包含默认的 MainMenu xib 和我的 CustomView xib。我希望我的 CustomView.xib 显示在添加到我的 MainMenu.xib 的自定义视图中——使用尽可能少的代码。

【问题讨论】:

    标签: objective-c cocoa nsview


    【解决方案1】:

    要加载您需要在窗口中添加的视图:- 创建了继承到 NSViewController 的自定义视图类

    #import <Cocoa/Cocoa.h>
    
    @interface NewViewController : NSViewController
    
    @end
    
    #import "NewViewController.h"
    
    @implementation NewViewController
    
    - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Initialization code here.
        }
    
        return self;
    }
    
    @end
    

    您的 xib 名称是 yourview.xib

    - (void)windowDidLoad {
        NSViewController *yourVC = [[NewViewController alloc] initWithNibName:@"NewViewController" bundle:nil];
        [[[self window] contentView] addSubview:[yourVC view]];
    }
    

    【讨论】:

    • 所以我需要以编程方式初始化视图/控制器并将其添加到主视图中的自定义视图中?之后我还需要以编程方式在两个视图之间添加约束。
    • 是的,首先您需要使用 xib 创建继承到 NSViewController 的自定义类,然后您可以在代码中加载与上面编写的相同的 xib。也供您参考,我已经更新了代码
    【解决方案2】:

    听起来您需要一个容器视图。但我认为您必须使用情节提要才能在界面生成器中使用它。

    【讨论】:

    • 它不适用于 iOS,所以故事板不是一个选项?
    • 好吧,对不起,我的错。仅针对 iOS 开发
    【解决方案3】:

    使用视图控制器,因为它会为您处理 nib 加载,并提供一个以可重用方式连接 IBOutletIBActions 的地方。

    在您的应用委托或任何控制器中创建视图控制器的实例。 要求您的视图控制器加载其视图。 将返回类型转换为您的视图类名称。 然后保留对您的视图控制器和可能的视图的引用。

    告诉任何视图将您的视图添加为子视图。 添加任何布局约束。 (当superview 或window 不为零时,您可以通过覆盖viewDidMoveToSuperviewviewDidMoveToWindow 来构建非常通用的约束以将它们自己添加到您的视图或视图控制器中。使用相同的约束来删除您的约束。)

    奇怪的是,您通过告诉视图将其自身从其superview 中删除来删除视图。

    【讨论】:

    • 如何将视图控制器链接到 Xib 文件?
    • 没有真正的链接。您将 nib/xib 文件的名称作为字符串传递给 initWithNibName:bundle: 并始终使用 NSBundle bundleForClass: 来传递包。这使其可重用,并且不会像 NSBundle mainBundle 那样耦合到应用程序包。 bundle 的 nil 与 NSBundle mainBundle 相同。您的 nib/xib 应该将文件的所有者类设置为 NSViewController 或子类。子类使 IB 能够识别自定义 IBOutlets!但你总是可以在代码中连接东西并进行转换,有时你应该这样做。
    【解决方案4】:

    我建议以编程方式进行:

    1. 将视图添加到您的主 xib/storyboard 并将自定义类设置为您的自定义视图的类
    2. 在自定义视图的 xib 中,将 File's Owner 类设置为自定义视图的类
    3. 根据需要连接任何IBOutlets
    4. 创建一个 __strong 属性/ivar,用于保存对 xib 的顶级 NSView 的引用
    5. 在自定义视图的类中实现initFromFrame,大致如下:
    @interface 自定义视图 () { __strong NSView *nibView; } @结尾 @实现自定义视图 - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; 如果(自我){ NSArray *nibObjects; [[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self topLevelObjects:&nibObjects]; nibView = nibObjects[1]; [自我 addSubview:nibView]; } 回归自我; }

    IBOutletloadNibNamed 调用后立即连接,因此您可以从那里进行进一步的初始化。

    另一种选择是纯粹以编程方式做事: 1. 在您的自定义xib 中,将根视图的类设置为您的自定义类 2.在你的自定义类中实现awakeFromNib来执行初始化 3. 在您的自定义 xib 上调用 loadNibNamed: 并以编程方式将其添加到用户界面,无需界面生成器。

    【讨论】:

    • 任何解释你为什么使用nibObjects[1]而不是nibObjects[0]
    • 我只是在尝试这个时得到一个编码器错误:致命错误:init(coder:) 尚未实现:
    猜你喜欢
    • 1970-01-01
    • 2010-10-26
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 2020-07-06
    • 2011-08-25
    • 2015-08-23
    • 1970-01-01
    相关资源
    最近更新 更多