以编程方式从nib的NSView子类中加载对象 [英] programmatically loading object from subclass of NSView from nib

查看:1714
本文介绍了以编程方式从nib的NSView子类中加载对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何使用Xib正确加载一个NSView的子类的对象?



我希望它从一开始动态加载,所以我做了一个MyView.Xib
从MyDocument.m我做了:

  MyView * myView = [[MyView alloc] initWithFrame :. ..]; 
[NSBundle loadNibNamed:@MyViewowner:myView];
[someview addSubview:myView];
...

和背景很好(它调用drawrect:预期)
,但我放在xib上的所有按钮不会出现。
我已经检查,并且他们被加载,但他们的superview不是与 myView 相同的对象。



为什么?我想我在XIB中缺少一些东西,但我不知道究竟是什么。
换句话说:我如何确保我的xib中的根视图是与文件所有者相同的对象?



我希望有类似的东西这对于mac:

  NSArray * nibViews = [[NSBundle mainBundle] loadNibNamed:@MyViewowner:self options:nil ]; //在iOS中这将加载xib 
MyView * myView = [nibViews objectAtIndex:1];
[someview addSubview:myView];
...

提前感谢。



EDIT



我认为我已经意识到问题的根源...(??)



在MyView类中,我有各种IBOutlet在IB中正确连接,这就是为什么他们加载正好(我可以引用他们)。但是顶视图没有IBOutlet。所以当NSBundle加载nib时,顶视图被分配给一些其他对象。我认为这将发生,如果我在IB中设置我的顶视图从类: MyView 并把 myView 作为所有者在 [NSBundle loadNibNamed:@MyView所有者:myView]; 但似乎不是这样的。
我做错了什么?

解决方案

请注意,nib文件包含:




  • 一个或多个顶级对象。例如, MyView ;

  • 文件的所有者占位符的实例。这是在加载nib文件之前存在的对象。



场景1: code> NSNib



让我们考虑一下你的nib文件只有一个顶级对象,其类别是 MyView ,文件的所有者类为 MyAppDelegate 。在这种情况下,考虑到nib文件是在 MyAppDelegate 的实例方法中加载的:

 code> NSNib * nib = [[[NSNib alloc] initWithNibNamed:@MyViewbundle:nil] autorelease]; 
NSArray * topLevelObjects;
if(![nib instantiateWithOwner:self topLevelObjects:& topLevelObjects])//错误

MyView * myView = nil;
for(id topLevelObject in topLevelObjects){
if([topLevelObject isKindOfClass:[MyView class]){
myView = topLevelObject;
break;
}
}

//此时myView是nil或指向一个实例
// MyView所拥有的实例

看起来像 - [NSNib instantiateNibWithOwner:topLevelObjects:] 可以是 nil ,所以你不必指定所有者,因为似乎你不想有一个:

  if(![nib instantiateWithOwner:nil topLevelObjects:& topLevelObjects])//错误


请注意,您拥有所有权



场景2: NSViewController



Cocoa提供 NSViewController 来管理视图;通常,从nib文件加载的视图。您应该创建一个 NSViewController 的子类,其中包含需要的插件。编辑nib文件时,请设置视图插座以及您可能已定义的其他插座。您还应该设置nib文件的所有者,以使其类是 NSViewController 的此子类。然后:

  MyViewController * myViewController = [[MyViewController alloc] initWithNibName:@MyViewbundle:nil]; 

NSViewController 自动加载nib文件和集当您发送 -view 时,相应的出口。或者,您可以强制它通过发送 -loadView 加载nib文件。


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?

解决方案

Note that a nib file contains:

  • One or more top-level objects. For example, an instance of MyView;
  • A file’s owner placeholder. This is an object that exists prior to the nib file being loaded. Since it exists before the nib file is loaded, it cannot be the same as the view in the nib file.

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 is MyAppDelegate. In that case, considering that the nib file is loaded in an instance method of MyAppDelegate:

NSNib *nib = [[[NSNib alloc] initWithNibNamed:@"MyView" bundle:nil] autorelease];
NSArray *topLevelObjects;
if (! [nib instantiateWithOwner:self topLevelObjects:&topLevelObjects]) // error

MyView *myView = nil;
for (id topLevelObject in topLevelObjects) {
    if ([topLevelObject isKindOfClass:[MyView class]) {
        myView = topLevelObject;
        break;
    }
}

// At this point myView is either nil or points to an instance
// of MyView that is owned by this code

It looks like the first argument of -[NSNib instantiateNibWithOwner:topLevelObjects:] can be nil so you wouldn’t have to specify an owner since it seems that you aren’t interested in having one:

if (! [nib instantiateWithOwner:nil topLevelObjects:&topLevelObjects]) // error

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 of NSViewController containing whichever outlets are needed. When editing the nib file, set the view 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 of NSViewController. Then:

MyViewController *myViewController = [[MyViewController alloc] initWithNibName:@"MyView" bundle:nil];

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.

这篇关于以编程方式从nib的NSView子类中加载对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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