Re: Is it possible to pass an object to a NIB
Re: Is it possible to pass an object to a NIB
- Subject: Re: Is it possible to pass an object to a NIB
- From: Ken Thomases <email@hidden>
- Date: Sat, 5 Dec 2009 09:55:00 -0600
On Dec 4, 2009, at 9:47 PM, DeNigris Sean wrote:
I'm trying to unit test a view class. As it is very thin (just
delegates all work to the controller), all I want to check is that
my connections (e.g. outlets and actions) are hooked up correctly.
I've been trying to:
1. Create an instance of my class
2. use NSBundle::loadNibFile: externalNameTable: withZone: to load
the nib
You'd normally write this +[NSBundle
loadNibFile:externalNameTable:withZone:] (or starting with '-' if
you're referring to the instance method).
3. check the connections
The docs for loadNibFile (http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ApplicationKit/Classes/NSBundle_AppKitAdditions/Reference/Reference.html
) seem to suggest that you can pass objects in:
"A name table whose keys identify objects associated with your
program or the nib file. The newly unarchived objects from the nib
file use this table to connect to objects in your program."
You can really only pass in the NIB owner object. In the NIB, there's
a proxy "virtual" object called File's Owner. Other objects in the
NIB can target File's Owner for actions, bind to File's Owner, or
connect their outlets to File's Owner. (It's actually more typical to
connect outlets of the File's Owner to the other objects.)
When the NIB is loaded, the object you specify as the actual owner is
plugged into the empty slot in the object graph represented by File's
Owner, thereby connecting the newly-loaded object graph to your
existing object graph.
The NIB also may have a proxy for the application object (NSApp),
which is another way for the newly-loaded object graph to be connected
to the existing object graph.
There are many methods for loading a NIB. The one you selected is
perhaps the clumsiest. That said, the external name table provides a
way to supply the NIB owner and receive the loaded top-level objects
of the NIB. To supply the owner, the dictionary should have a key
NSNibOwner mapping to the object to become the owner.
This code is in ruby, but it's just bridged to the corresponding
Cocoa calls:
view = MyView.new # subclass of NSWindowController
Which is it, a view or a window controller? Those are two radically
different things, and you're confusing matters (and perhaps yourself)
by naming a window controller a "view".
You normally wouldn't instantiate a view if you're going to be loading
a chunk of GUI from a NIB. The NIB would have a "freeze-dried" view
hierarchy and loading the NIB would instantiate it for you.
As Chris Hanson said, if you're really instantiating a window
controller here, then you should let it load the NIB and establish
itself as the owner.
NSApplication.sharedApplication
top_level = [] # I've tried passing everything I could think of here:
- view # the object instance
- "My View" => view # NSDictionary with key object name in IB
and value object instance
- MyView => view # NSDictionary with class name / object entry
You don't pass in the top-level objects, you receive them. Or, you
can just not bother. An NSWindowController would manage this all for
you. In any case, if you want to receive them with the
loadNibFile:externalNameTable:withZone: method, you should pass an
empty NSMutableArray in the external name table dictionary, under the
NSNibTopLevelObjects key. The method would fill that array with the
top-level objects.
Also, if you're using an NSWindowController in the typical way, it
does not reside in the NIB, at all. Instead, the File's Owner (which,
remember, is just a placeholder) is configured to be of the same class
as your custom NSWindowController subclass. Configuring it in that
way is just a means to get Interface Builder to know which outlets,
actions, and properties it supports to assist you at design time. It
has no real impact at runtime.
In this case, though, you want to pass your NSWindowController-
subclass instance as the owner of the NIB when it's loaded. You don't
pass or receive it as a top-level object, because it's not. It's not
"in" the NIB, at all.
By the way, names of objects in Interface Builder are for human
consumption only. They, too, have no runtime impact.
# I Also tried passing the object, and object-containing
dictionaries below
# e.g. dictionaryWithObjects_forKeys [NSApp, top_level, view],
[NSNibOwner, NSNibTopLevelObjects, "My View"]
context = NSDictionary::dictionaryWithObjects_forKeys [NSApp,
top_level], [NSNibOwner, NSNibTopLevelObjects]
This is somewhat closer, except I believe you wanted your window
controller to become the owner of the NIB. You're telling it to use
the application object as the owner of the NIB, which doesn't match
what you say you're trying to achieve. Also, it's not at all clear to
me that top_level is the proper type of object. That's a matter for
the RubyCocoa bridge, but loadNibFile:externalNameTable:withZone: is
expecting an NSMutableArray instance for that key.
NibPath = ".../RandomAppRuby.app/Contents/Resources/English.lproj/
MainMenu.nib"
OSX::NSBundle::loadNibFile_externalNameTable_withZone NibPath,
context, NSApp.zone
Regards,
Ken
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden