Re: nibs, subclassing nsview
Re: nibs, subclassing nsview
- Subject: Re: nibs, subclassing nsview
- From: Uli Kusterer <email@hidden>
- Date: Thu, 24 Aug 2006 11:38:33 +0200
Am 24.08.2006 um 10:19 schrieb Wagner Truppel:
I think the essential clue that may not have been made clear in
other people's replies is this: when creating a custom view (ie, an
NSView subclass corresponding to your custom view), you are *not*
supposed to actually *instantiate* it in Interface Builder. Rather,
you should
(a) only make IB *aware* of it, by dragging its interface file onto
the main IB window for your nib file,
(b) drag a custom view item from IB's palette to the window or
panel of your nib, where the custom view is supposed to sit (and
then configure its size and other such properties), and
(c) set its class to match the intended subclass of NSView, using
the appropriate IB's Inspector window.
Then, it's up to you to *programatically* create an actual instance
of that custom view, using the code that others have already
suggested.
Errr... this could be easily misunderstood. Let me explain some more:
If you create a (custom) view that is a separate top-level object
in the NIB file, it is free-floating (i.e. its -superview and -window
methods will return NIL). One of the ways you do this (and I think
the only way under 10.2) is using the "Instantiate" menu item. If you
create a custom view inside a window (like points b and c
illustrate), you're actually instantiating an instance of the same
class, but you're not going through the "Instantiate" menu item.
These two views are two separate instances of the same *class*. Two
separate objects.
To insert a free-floating view in another view in a window, do it
programmatically, using addSubview: or a similar method
(setDocumentView: in the case of scroll/clip views). Don't do that in
-init, though. Views get -initWithFrame:, not -init, and the other
objects may not exist yet at -init(WithFrame:) time. So do that in -
awakeFromNib, where it's guaranteed the other objects have already
been created.
(BTW: Just to cover all bases: You need to make sure you've added the
source files for your view to any project that uses the NIB file.
Dragging a header on IB only tells IB how to save your view in a NIB
file, it doesn't in any way store the code for the view)
Note that this is different from what you do with other kinds of
objects, for which you actually create an instance from within IB
itself.
Again, in both cases you're creating instances in IB. It's just
that for most other custom classes you're using the "Instantiate"
menu item to get a top-level object (the blue box), whereas views are
usually instantiated inside their window by taking an NSView and
changing its class using the "Custom Class" pane.
So, what happened in your case is that you created an actual
instance of your custom view, from within IB, added buttons and
such to it, but that custom view object was never "seen" by your
code, because your code didn't create it. What your code did create
and drew on was *another* instance of your custom view, but not the
one which you added the buttons and such to.
If you want to access anything created in IB, you need to create an
IBOutlet and hook it up to the actual object. That's the only way to
get a pointer to an object in a NIB, and you need a pointer to get at
the object to use or manipulate it directly. NSViews aren't in any
way special in this regard. Yes, calling alloc/init on a class will
create a *new* object, not give you access to any of the objects you
defined in the NIB. However, it is not necessary to programmatically
create a view using alloc/init. It's perfectly fine to just set up
all of that in a NIB.
Now, the OP mentioned there was a bug with certain nesting of
certain views which forced creating a top-level view (haven't
encountered it yet, too lazy to reproduce it). Well, that sucks, file
a bug, blah, blah... still, since it's a top-level object, what's
needed is probably explicitly (i.e. programmatically) adding that top-
level view to the superview. The easiest way is to put a placeholder
view (just a plain NSView) into the window and then replace that with
the top-level view. replaceSubview:atIndex: or whatever the method is
called does that.
Cheers,
-- M. Uli Kusterer
http://www.zathras.de
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden