Short version:
- Why don't NSView subviews send a
release message when a Cocoa application terminates? - Is there any way to undo this behavior?
Example:
The MyView class shown below is nothing more than a subclass of NSView , which is sent to the console when it is created and destroyed. I checked it and found that it was working correctly. However, when I use it, as shown in the following code snippet from my application delegate, I see something unexpected (see Sample output).
// MyView: @interface MyView : NSView { } @end @implementation MyView - (id)initWithFrame:(NSRect)frameRect { if ((self = [super initWithFrame:frameRect]) == nil) { return nil; } NSLog(@"init %@", self); return self; } - (void)dealloc { NSLog(@"dealloc %@", self); [super dealloc]; } @end
// Application delegate: - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { NSLog(@"begin"); parentView = [[MyView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]; MyView * myView = [[MyView alloc] initWithFrame:NSMakeRect(10, 10, 80, 80)]; [parentView addSubview:myView]; [myView release]; NSLog(@"run"); } - (void)applicationWillTerminate:(NSNotification *)aNotification { NSLog(@"quit"); [parentView release]; NSLog(@"end."); }
This application displays the following result:
begins
init < MyView: 0x10013f840 >
init < MyView: 0x10261b620 >
run
quit
dealloc < MyView: 0x10013f840 >
end.
Problem:
I can clearly see that the first view object is freed when the application exits, and I am sure (checked and verified) that NSView objects automatically free their routines when they themselves are freed. However, it seems that during the termination of the application, these subclauses are not freed.
Long version: (AKA, why, in fact, will anyone care? :)
Let me start by saying that I am familiar with how memory is freed by a running application when it exits. I know that my subtitles will be disposed of correctly even if they are never sent a release message, so I donโt worry about it being a leak. In fact, I'm sure (but not 100% sure) that the answer to my question is No. 1: "Because the release of subqueries is not required when the application is about to end."
I am using some simple manual code to track memory while my application is in debug mode. I make calls to the Trace_Init() and Trace_Dealloc() methods in the init and dealloc methods of all my custom classes, and I use the atexit() function to report any unreleased objects after the Cocoa part of my application is completed. I find this a lot easier than regularly using the tool to improve Apple's memory performance. If I cause a memory leak during operation, I will find out about it as soon as my application closes.
However, the absence of a call to dealloc during termination means that any of my custom NSView subclasses that are used as NSView are detected as a memory leak when exiting the application. So the reason for my question is # 2. I would like Cocoa to free everything at completion so that memory tracking can end normally. Naturally, I would only cancel the default behavior in debug mode. None of the memory tracking code is included in my released application, and it should be able to exit it as efficiently as usual.
What is it! (phew) If you made it this far, thanks for taking the time to read it all.