Pregunta

I'm encountering a strange situation with NSWindowController. I want the window controller to be released but it will not. It doesn't seem to be following my expectations for ARC behavior.

I've created a simple window controller subclass, PlainWindowController. Its interface and implementation are empty:

#import <Cocoa/Cocoa.h>

@interface PlainWindowController : NSWindowController
@end

@implementation PlainWindowController
@end

I created with it a default windowController xib named PlainWindowController.xib, which has a window with delegate and windowController connections already set.

In a test, I've written this code:

PlainWindowController *strongWindowController = [[PlainWindowController alloc] initWithWindowNibName:@"PlainWindowController"];
__weak PlainWindowController *weakWindowController = strongWindowController;

[strongWindowController showWindow:nil];

strongWindowController = nil;
STAssertNil(weakWindowController, @"The window controller should have been deleted, wasn't");

When this test runs, the weak reference is not nil.

If I leave out the showWindow it is nil. If I use init instead of initWithWindowNibName, it is nil.

Does anyone know what's going on here? Thank you in advance for any guidance.

¿Fue útil?

Solución 2

You generally shouldn't harbor "expectations" about when objects are deallocated if they've ever been passed to other code which you don't control.

Cocoa might have retained and then autoreleased the controller. Cocoa may retain the window controllers of any windows which are showing.

In general, when it comes to Cocoa memory management, you are supposed to make sure your own code follows the rules (which ARC largely does for you) and you should assume that other code follows the rules, but you can't assume that other code doesn't retain objects beyond where your interest ends. You should basically not care about what the other code is doing with respect to memory management.

If you really want to know what's happening, run your app under the Allocations instrument and explore the retain/release/autorelease history of your object after the point where you expected it to have been deallocated.

Otros consejos

There’s no guarantee that an object under ARC hasn’t been added to the autorelease pool, in which case it won’t be freed until the end of the current event.

In your case, I strongly suspect somewhere within initWithWindowNibName: the controller gets retained and autoreleased.

If you really want to ensure your object is being freed, just subclass the -dealloc method and add an NSLog to it or break on it.

I had a similar issue when first using ARC. I unfortunately don't remember the details as this was more than a year ago. I eventually tracked it down as a circular retain problem using Instruments to monitor retain values, although not without losing a lot of hair.

I think the actual problem was with the delegate which I fixed with @property (unsafe_unretained) id delegate;

I ran into a similar issue yesterday with an ARC based project - a NSWindowController subclass would not deallocate, nor did -dealloc fire. I worked with Zombies, Allocations to no avail. The problem was very simple. There was a subclassed control within the window, and in that controls subclass .h header file a property was defined as:

@property id delegate;

correcting it to

@property (nonatomic, weak) id delegate;

fixed the issue.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top