Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

BadWolf13

macrumors 6502
Original poster
Dec 17, 2009
271
0
I'm writing a multi-window program in Cocoa. When a user clicks on a certain button in the main window, it opens a second window, for which I have a custom subclass of NSWindowController. When the user closes that second window, it stays in memory, which is creating a bit of a memory waste, and also can also create the following error message in the console, which is related to the bindings in the window.

<NSKeyValueObservance 0x10028e740: Observer: 0x1001cf530, Key path: available, Options: <New: NO, Old: NO, Prior: NO> Context: 0x0, Property: 0x100268150>

Any ideas how I can just completely deallocate the window controller when the user closes the window? Given how many windows can be open at once in this window, I'd rather not have any non-open windows taking up active memory space. I've tried using
Code:
[self dealloc]
and
Code:
[self autorelease]
but neither one worked.
 
In your main controller you could watch for window close notifications, then grab the window's controller via [window windowController] and release it there (or store the window controllers in an array).

Or in your window controller, call [self retain] at init, and [self release] in windowDidClose: and when you create the window controller, create it as an autoreleased object.

Hint: never call dealloc directly. It's called automatically when the retain count goes to 0.
 
Ok, couple of questions from the. First, if I were to store my window controllers(this program will often have multiple instances of this window open at once), wouldn't that waste more memory, unless I find a way to remove the objects from the array when the window closes?

Second question. My understanding is that when you use Garbage Collector, you don't need to bother with Autorelease, release and retain, that the Garbage Collector takes care of that on it's own. Was I wrong?
 
No, you're right. Since you're using GC you'll want to store references to the controllers in an array, then when the window closes (you can watch for the notifications), remove the controllers from the array. That at least is how I'd do it in GC.
 
Is windowDidClose a notification or a method? I tried putting in a method called windowDidClose, but it was never called when I closed the window.
 
You need to use NSNotificationCenter to watch notifications of type NSWindowWillCloseNotification.
 
Or, you don't have to register as a notification observer. If your window controller is your window's delegate, just write up a method:

Code:
- (BOOL)windowDidClose:(id)sender { … }

No need to declare it in your header, it will get called automatically by your window. So yes, windowDidClose: is a notification and a method, but only if the window controller is the window's delegate.
 
^ That only applies within the window controller. If you're wanting to free the window controller when the window closes in a GC environment you'd have to communicate to your main controller this somehow.
 
Hey Kainjow, I took your advice and changed the windowController to an array, but I'm still getting the same error when I dealloc the windowController. It seems tied to the key-value bindings in the XIB file. Is there a way to release those bindings in the code within the dealloc method? Would that even solve this?
 
I did a google search and came across the same problem that everyone else is having. Apparently the bindings cause wayyyyy too many retains. Someone said they found something like 8. The main workaround I saw involved using an NSObjectController, and set the content as the model object.

The thing is, for my application, all the bindings are connected to a single BOOL variable for the "Enabled" status of my text fields and buttons. I'm thinking I could just use glue code to set the enabled status. It's a lot of glue code, but it would get rid of this problem. Anyone got any better ideas?
 
I would think that any memory leakage is a big deal. Especially in a program that will have an unlimited number of windows open at any given time, and that's meant to be used in a business setting where a session will typically be the entire work day. That's potentially a lot of memory leakage.

Ignoring the existing application, there is potential for this problem arising again in the future, and seeking to understand it's implications and solutions will help make me a more effective programmer. In short, I don't walk away from problems, I face them.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.