以编程方式从 nib 的 NSView 子类加载对象
如何使用 Xib 正确加载 NSView 子类的对象?
我希望它动态加载,而不是从一开始就加载,所以我做了一个 MyView.Xib 从 MyDocument.m 我做了:
MyView *myView = [[MyView alloc] initWithFrame:...];
[NSBundle loadNibNamed:@"MyView" owner:myView];
[someview addSubview:myView];
...
并且背景很好(它调用drawrect:并且按预期绘制) 但我放在 xib 上的所有按钮都不会出现。 我已经检查过,它们已加载,但它们的超级视图与 myView
不是同一对象。
这是为什么呢?我想我在 Xib 中遗漏了一些东西,但我不知道到底是什么。 换句话说:如何确保 xib 中的根视图与文件所有者是同一对象?
我希望 Mac 上有类似的东西:
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil]; //in iOS this will load the xib
MyView* myView = [ nibViews objectAtIndex:1];
[someview addSubview:myView];
...
提前致谢。
编辑
我想我已经意识到问题的根源...(??)
在MyView类中我有各种IBOutlet,它们在IB中正确连接,这就是为什么它们加载得很好(我可以参考它们)。然而,顶视图没有 IBOutlet。因此,当 NSBundle 加载笔尖时,顶视图会被分配给其他某个对象。我认为如果我将 IB 中的顶部视图设置为来自类:MyView
并将 myView
作为 [NSBundle loadNibNamed:@"MyView] 中的所有者,就会发生这种情况“owner:myView];
但事实似乎并非如此。 我做错了什么?
How do I correctly load an object that is a subclass of NSView using a Xib?
I want it to be loaded dynamically not from the beginning so I made a MyView.Xib
From MyDocument.m I did:
MyView *myView = [[MyView alloc] initWithFrame:...];
[NSBundle loadNibNamed:@"MyView" owner:myView];
[someview addSubview:myView];
...
and the background is fine (it calls drawrect: and it's drawn as expected)
but all the buttons I put on the xib won't appear.
I have checked, and they are loaded BUT their superview is not the same object as myView
.
Why is this? I think I am missing something in the Xib but I don't know exactly what.
In other words: How do I make sure that the root view in my xib is the same object as file's owner?
I wish there was something similar to this for the mac:
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil]; //in iOS this will load the xib
MyView* myView = [ nibViews objectAtIndex:1];
[someview addSubview:myView];
...
Thanks in advance.
EDIT
I think I have realised the origin of the problem...(??)
In MyView class I have various IBOutlet which are connected correctly in IB that is why they load just fine (I can refer them). However there is no IBOutlet for the top view. So when NSBundle loads the nib, the top view gets assigned to some other object. I thought this will happen if I set my top view in IB to be from class:MyView
and put myView
as the owner in [NSBundle loadNibNamed:@"MyView" owner:myView];
but it seems not to be the case.
What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
请注意,nib 文件包含:
MyView
的实例;场景 1:
NSNib
假设您的 nib 文件只有一个顶级对象,其类为
MyView
,文件的所有者类为MyAppDelegate
。在这种情况下,考虑到 nib 文件是在 MyAppDelegate 的实例方法中加载的:看起来
-[NSNib instantiateNibWithOwner:topLevelObjects:]
的第一个参数可以是 < code>nil 因此您不必指定所有者,因为您似乎对拥有一个所有者不感兴趣:虽然这有效,但我不会依赖它,因为它没有记录。
请注意,您拥有顶级对象的所有权,因此您有责任在不再需要它们时释放它们。
场景2:
NSViewController
Cocoa提供
NSViewController
来管理视图;通常,视图是从 nib 文件加载的。您应该创建一个 NSViewController 的子类,其中包含所需的插座。编辑 nib 文件时,设置view
出口以及您可能定义的其他出口。您还应该设置 nib 文件的所有者,使其类是 NSViewController 的子类。然后:NSViewController
在发送-view
时自动加载nib文件并设置相应的outlet。或者,您可以通过发送-loadView
强制它加载 nib 文件。Note that a nib file contains:
MyView
;Scenario 1:
NSNib
Let’s consider that your nib file has only one top-level object whose class is
MyView
, and the file’s owner class isMyAppDelegate
. In that case, considering that the nib file is loaded in an instance method ofMyAppDelegate
:It looks like the first argument of
-[NSNib instantiateNibWithOwner:topLevelObjects:]
can benil
so you wouldn’t have to specify an owner since it seems that you aren’t interested in having one:Although this works, I wouldn’t rely on it since it’s not documented.
Note that you have ownership of the top level objects, hence you are responsible for releasing them when they’re no longer needed.
Scenario 2:
NSViewController
Cocoa provides
NSViewController
to manage views; usually, views loaded from a nib file. You should create a subclass ofNSViewController
containing whichever outlets are needed. When editing the nib file, set theview
outlet and whichever other outlets you may have defined. You should also set the nib file’s owner so that its class is this subclass ofNSViewController
. Then:NSViewController
automatically loads the nib file and sets the corresponding outlets when you send it-view
. Alternatively, you can force it to load the nib file by sending it-loadView
.可以参考这个分类
https://github.com/peterpaulis/NSView-NibLoading- /树/主
You can refer to this category
https://github.com/peterpaulis/NSView-NibLoading-/tree/master
我发现 @Bvarious 的答案非常有用,但我仍然需要一些松鼠才能使其适合我的用例 - 将几个 xib 的视图定义之一加载到现有的“容器”视图中。这是我的工作流程:
1) 在 .xib 中,按预期在 IB 中创建视图。
2) 不要为新视图的 viewController 添加对象,而是
3) 将 .xib 的文件所有者设置为新视图的 viewController
4) 连接任何插座和对文件所有者的操作,特别是
.view
5) 调用 loadInspector(见下文)。
I found the answer by @Bavarious very useful, but it still needed some squirrelling on my part to make it work for my use case - load one of several xib's view definitions into an existing "container" view. Here's my workflow:
1) In the .xib, create the view in IB as expected.
2) DO NOT add an object for the new view's viewController, but rather
3) Set the .xib's File's Owner to new view's viewController
4) Connect any outlets & actions to File's Owner, and, specifically,
.view
5) Call loadInspector (see below).
这是一种编写 NSView 子类的方法,因此视图本身完全来自单独的 xib,并且所有内容都设置正确。它依赖于
init
可以更改self
的值这一事实。使用 Xcode 创建一个新的“视图”xib。将文件所有者的类设置为 NSViewController,并将其
view
出口设置为您的目标视图。将目标视图的类设置为您的 NSView 子类。布局你的视图,连接插座等。现在,在你的 NSView 子类中,实现指定的初始化器:
与
initWithCoder:
相同,这样在另一个 xib 中使用你的 NSView 子类时它也可以工作。Here is a way to write the NSView subclass so the view itself comes fully from a separate xib and has everything set up correctly. It relies on the fact that
init
can change the value ofself
.Create a new 'view' xib using Xcode. Set the File Owner's class to NSViewController, and set its
view
outlet to your target view. Set the class of the target view to your NSView subclass. Layout your view, connect outlets etc.Now, in your NSView subclass, implement the designated initializers:
And the same with
initWithCoder:
so that it will also work when using your NSView subclass in an another xib.}
}