Search code examples
objective-cmacoscocoaautomatic-ref-countingnswindowcontroller

NSWindowController subclass will not release in ARC


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.


Solution

  • 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.