Re: of nibs and top level objects
Re: of nibs and top level objects
- Subject: Re: of nibs and top level objects
- From: Paul Forgey <email@hidden>
- Date: Mon, 10 Apr 2006 01:02:23 -0700
Ughh this retain stuff can still be confusing. The meaning of his
comment finally struck me stupid:
// nibInstantiateWithOwner retains each top level object
[topLevelObjects makeObjectsPerformSelector:@selector
(release)];
Which means that we wasn't intending the objects to be left owned by
the array, but to be not doubly retained by being in the array. Of
course that would make sense (duh) as he's getting this array by
looking it up from another container.. So it wasn't a coincidence my
retain count went down by 14 but still needed another 14 to be
finally released.
I also thought of some more productive search terms and found out
things have improved since 2003.. His solution seemed to be a bit
messy in an un-Cocoa way, although I appreciate in the context of
Application Kit missing NSNib.
Between the NSBundle, NSBundle additions, NSNib, NSNibAwakening,
NSNibConnector, NSNibControlConnector, NSNibOutletConnector I got
lost in the pile of documentation on this.
Although a bit simplistic for general purpose, this ended up solving
my problem:
static NSMutableDictionary *nibsByName;
@implementation NSNib ( NibExtensions )
+ (BOOL)instantiateNibNamed:(NSString *)name owner:(id)owner
topLevelObjects:(NSArray **)topLevelObjects
{
NSNib *nib;
if (!nibsByName)
nibsByName = [[NSMutableDictionary alloc] initWithCapacity:0];
nib = [nibsByName objectForKey:name];
if (!nib)
{
nib = [[NSNib alloc] initWithNibNamed:name bundle:nil];
if (!nib)
return NO;
[nibsByName setObject:nib forKey:name];
[nib release]; // give it to the dictionary
}
return [nib instantiateNibWithOwner:owner
topLevelObjects:topLevelObjects];
}
@end
On Apr 10, 2006, at 12:51 AM, Paul Forgey wrote:
Thanks for replying.. my answers interlaced in yours
On Apr 10, 2006, at 12:31 AM, j o a r wrote:
On 10 apr 2006, at 09.06, Paul Forgey wrote:
When the node is no longer needed, it is told to "unload" and
hopefully releases all the top level nib items.
Hopefully? As in that's what it should do, but it seems that it
doesn't?
Well, I am releasing them. If I am releasing all of them or not
would depend on the code providing them to me to be working.
I'm having a lot of trouble doing this. I've managed to account
for about 14 retain counts, which is about 14 short of the total
needed to bring the total count back to 0.
Among your retain events, are there any suspects? Anything related
to bindings?
They all seem to be coming from the process of instantiating the
nib. If I put a breakpoint in my retain method (which of course
just returns [super retain] but allows me to trap it) the call
stack shows them all coming from the process of instantiating the
nib contents.
If the node loads a nib file, it never goes away.
The node?
A "node" is an object which represents the data contained in a tree
view item. There are detail views which are specific to the type
of object contained, which are demand loaded from nib files. They
may even be instantiated more than once for different owners, as
the nodes own these instantiations.
It should be enough to just say these "nodes" are objects owning
the nib instance.
In the list archives, I stumbled over this bit of code following
and it seems to be giving back a reasonable list of items. By
retaining the array I hold onto the items, then release the array
when I'm done.
What do you hope to accomplish by doing this, compared with
regular nib loading?
When you're tracking retain-release events, do you see that it
makes any difference?
If I don't load the nib, everything cleans up properly. I know for
a fact this is where my overretaining problem is coming from.
Similar to how an application may have more than one view of more
than one document, and thus specific instances of nib contents
owned by those entities, my documents controllers have a similar
need to instantiate UI objects contained in nib files more than
once for different top level tree items.
What more do I need to do, and is there clearer documentation
than what's in the Application Kit section about NSBundle
additions which just says I need to "release all the top level
items" with no further information about how to actually _do_ this?
In the general case you would just have to do this:
- (void) dealloc
{
[topLevelNibObject release];
// ...repeat for other top level objects
[super dealloc];
}
The problem when that is the top level items are retaining me, so
I'll never get dealloc'd. I do, however, have a mechanism in my
application to tell these nodes to "unload", where I am releasing
the top level items, similar to how a window controller probably
does when it's associated document closes.
Yes, it's being called and I can indeed see the retain count go
down as a consequence of doing so.
If an object is loading multiple nib files during it's lifetime,
it would of course have to do more work in order to keep track of
it's top level items - but the theory is the same. It's just basic
Cocoa memory management. When you load a nib file you assume
memory management ownership of the top level items, meaning that
you have to release them at the appropriate time. There's nothing
more to it.
One thing that may be complicating matters is there are bindings
in this nib referring to objects in the document window
controller's nib. That object owning the document nib is not
over-retained. It still dealloc's when the document closes.
No, they're not referring to object in some other nib file -
because cross-nib connections are not supported (This is a detail
of course, but for this discussion I think it would be better if
you make a clear distinction between archived objects in a nib
file and "live" objects at runtime.). They might of course still
reference the actual window controller, via key paths or otherwise.
That makes sense since there are bindings to key paths involving
the controller, yet my window controller dealloc's fine.
One thing that may be complicating matters is there are bindings
in this nib referring to objects in the document window
controller's nib. That object owning the document nib is not
over-retained. It still dealloc's when the document closes.
Do you have any evidence to support the idea that bindings are
related to your problem? If you remove the bindings (work on a
copy of your project / nib), does it work as expected?
How about setting up and tearing down your bindings manually in
code? At least it might be good for troubleshooting purposes.
Bindings might have nothing to do with my problem, or everything.
I don't know. I just thought I'd point out that I'm using them in
case it's important for the solution.
j o a r
_______________________________________________
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
_______________________________________________
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