-[Ventana NSWindowController] Ventana de retención cuando NSWindowController se inicializó con la ventana?
-
27-10-2019 - |
Pregunta
En una aplicación (OS X 10.6.7) tengo un NSWindowController
subclase que se inicializa con -[NSWindowController initWithWindow:]
—Ie, ya he creado la ventana en código; No lo estoy cargando de una punta.
Normalmente, me refiero a la ventana de mi NSWindowController
subclases con [self window]
. Pero en este caso, cada vez que envío [self window]
, la ventana se conserva, así que termino con una fuga bastante.
¿Es este comportamiento previsto? Por el momento, he trabajado a su alrededor simplemente almacenando la ventana en una variable de instancia en el init
método y nunca enviando [self window]
.
Estoy bastante seguro de que esto no está sucediendo porque NSWindowController
está tratando de cargar la ventana: -loadWindow
no retiene la ventana y -isWindowLoaded
devoluciones YES
:
(gdb) set $window = (id)[self window]
Current language: auto; currently objective-c
(gdb) p (int)[$window retainCount]
$1 = 3
(gdb) p (BOOL)[self isWindowLoaded]
$2 = 1 '\001'
(gdb) call (void)[self loadWindow]
(gdb) p (int)[$window retainCount]
$3 = 3
(gdb) p (int)[[self window] retainCount]
$4 = 4
(gdb) p (int)[[self window] retainCount]
$5 = 5
Solución
-[NSWindowController window]
retener la ventana está bien; El problema parece estar relacionado con las piscinas de autoresas.
window = [[NSWindow alloc] initWithContentRect:NSMakeRect(100, 100, 200, 200)
styleMask:NSTitledWindowMask
backing:NSBackingStoreBuffered
defer:NO];
NSWindowController *controller = [[NSWindowController alloc] initWithWindow:window];
[window setTitle:@"testing"];
[window makeKeyAndOrderFront:nil];
[window release];
NSLog(@"[window retainCount]: %d", [window retainCount]);
[controller window];
[controller window];
[controller window];
NSLog(@"[window retainCount]: %d", [window retainCount]);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[controller window];
[controller window];
[controller window];
NSLog(@"[window retainCount]: %d", [window retainCount]);
[pool drain];
NSLog(@"[window retainCount]: %d", [window retainCount]);
La salida es:
2011-06-12 19:26:52.337 window[5517:a0b] [window retainCount]: 1
2011-06-12 19:26:52.339 window[5517:a0b] [window retainCount]: 4
2011-06-12 19:26:52.340 window[5517:a0b] [window retainCount]: 7
2011-06-12 19:26:52.340 window[5517:a0b] [window retainCount]: 4
El problema era que olvidé crear una piscina al hacer cosas de cacao en un manejador de eventos de carbono (InstallApplicationEventHandler
). Esto coincide con el contexto del hilo al que me vinculé.
Por lo general, veo una excepción cuando no hay un grupo de autorlease presente, por lo que supongo que simplemente hay una piscina en su lugar que nunca se drena.