Bindings and File's Owner

There's an issue with Cocoa bindings that a number of people keep running into. Here's the short and simple:

If you have a nib in which File's Owner is a subclass of NSWindowController or NSDocument, do not bind anything through file's owner.

The problem is that bindings that go through File's Owner cause parents and children to retain each other, causing a memory leak that grows with each new window.

Dennis C. De Mars did some investigation into this, and came up with the simplest solution I've seen thus far:
  1. Create an NSObjectController
  2. Populate it after the nib wakes up using -setContent:
  3. Bind UI elements through the NSObjectController instead of File's Owner

I believe Apple is aware of the issue, but a workaround is necessary right now.
Design Element
Bindings and File's Owner
Posted Oct 11, 2004 — 11 comments below




 

Dan Wood — Dec 20, 04 45

There's an HTML glitch in the link to "simplest solution"....

http://www.cocoabuilder.com/archive/message/2004/7/28/113081

Scott Stevenson — Dec 22, 04 46 Scotty the Leopard

Fixed, thanks.

Steven Kramer — Jan 10, 05 59

I think the retain cycle problem is possible anywhere you bind to File's Owner and File's Owner properly retains its nib objects. Also, it doesn't manifest itself always (just tried to reproduce from scratch, no problem). Most importantly, I think you need a step 4 - use [objectControllerr setContent: nil] in a suitable method. For instance [NSDocument close].

Dan Stein — Feb 09, 05 83

Steven Kramer is quite correct. I modified Crawford's Manual Bindings example to a document-based app and it leaked like the dickens until I simply stuck in a line to set the content of the array controller to nil when the document window is closed.

Ricardo — May 03, 05 151

Hi,
Thanks for the articles about CoreData, just printed them and will have some night reading to do tonight...

I was wondering if you have some tutorials on NSController and NSArrayController

I read some stuff at apple and even play with them but i think i am missing the deep down idea on how to use them.

Thanks
Ricardo

Ricardo — May 03, 05 152

Hoops Sorry wrong thread

Matt Gallagher — Dec 12, 05 608

As of Mac OS X 10.4.3, NSDocument and NSWindowController seem to have this *almost* fixed. An undocumented class named NSAutounbinder seems to automagically perform an unbind for these two classes -- fixing the reference counted loop for Nib bindings.

This doesn't always work (quitting an application with a document window open that has no unsaved changes results in the document not getting unbound -- work around is to closeAllDocumentsWithDelegate manually on applicationShouldTerminate) and still doesn't fix the problem when the owner is neither an NSDocument nor NSWindowController.

In these "doesn't always work" situations, the NSObjectController fix described above still works.

Just so you know.

Jamie Kirkpatrick — Mar 20, 06 943

This is nice, but if you want to proxy the original file's owner in this way you'll need to go a little further.

In your NSWindowController subclass override awakeFromNib: and release with something that looks like this:

- (void) awakeFromNib;
{
// filesOwnerProxy == NSObjectController in the nib
[filesOwnerProxy setContent:self];
}

- (oneway void) release;
{
// special case when count is 3, we are being retained twice by the object controller...
if ( [self retainCount] == 3 )
{
[super release];
[filesOwnerProxy setContent:nil];
return;
}

[super release];
}

When you setContent: in the NSObjectController you get two extra retains in the new contentObject. This is a nice solution since you can be sure that the extra two retains will be from your objectController, and you can safely bind as much as you like to that controller. The only issue will be if apple changes their NSObjectController etc code.

Bruce Rakes — Feb 06, 07 3510

I was just bitten by this "bug" and spent some time implementing the above suggestions with success. However, this seems like a real kludge to me.

Does anyone know how Leopard and garbage collection will affect this?

Scott Stevenson — Feb 06, 07 3513 Scotty the Leopard

Does anyone know how Leopard and garbage collection will affect this
Garbage collection should make it a moot point.

Christiaan Hofman — Aug 23, 08 6305

If anyone is still reading this, be aware that this issue is still present in Leopard. I know of at least two reproducable cases where it occurs:

1. Binding to the File's Owner with key path "self" (this occurs when you use an NSObjectController 'proxy' for the File's Owner, e.g. to have a funnel point for NSEditor/NSEditorRegistration, as is recommended by many reputable people and the docs).

2. Binding an NSArrayController's contentArray to a to-many property of the File's Owner for which only indexed KVC accessors are implemented (i.e., not -<key> and -set<Key>:). Note that this is actually recommended practice (at least according to some people).




 

Comments Temporarily Disabled

I had to temporarily disable comments due to spam. I'll re-enable them soon.





Copyright © Scott Stevenson 2004-2015