Pregunta

Estoy atascado!

Estoy intentando crear un diálogo modal personalizado. Me gustaría que para llevar a cabo de manera similar a la NSSavePanel usando un bloque como un manejador de finalización.

He copiado sólo los fragmentos importantes que consideren necesarias.

@implementation ModalWindowController
    - (void)makeKeyAndOrderFront:(id)sender
                   modalToWindow:(NSWindow*)window
                      sourceRect:(NSRect)rect
               completionHandler:(void (^)(NSInteger result))handler {

        _handler = [handler retain];

        session = [NSApp beginModalSessionForWindow:[self window]];
        [[NSApplication sharedApplication] runModalSession:session];

        [[self window] makeKeyAndOrderFrontCentered:self expandingFromFrame:rect];
    }
    - (IBAction)okButtonPressed:(id)sender {
        [[self window] orderOut:self];
        _handler(NSOKButton);
        [NSApp endModalSession:session];
    }

@end

Ahora puede llamar a esto utilizando el código:

[self.modalWindowController makeKeyAndOrderFront:self
                                   modalToWindow:[[self view] window]
                                      sourceRect:sr
                               completionHandler:^(NSInteger result) {
    NSLog(@"Inside Block");
    if ( result == NSOKButton ) {
        // do something interesting here
    }
}];
NSLog(@"Errg");

Todo va bien, sin embargo, después de que el método makeKeyAndOrderFront: modalToWindow: sourceRect: completionHandler: ha completado que no bloquea el hilo, por lo que "errg" se imprimirá aunque el usuario no ha seleccionado "OK" o "cancelar". La ventana modal se muestra en este punto, donde se ejecuta entonces el usuario hace clic en OK y el bloque _handler. Sin embargo, si estoy tratando de acceder a las variables locales en el bloque, y la aplicación se bloquea, ya que todo ha limpiado ya.

¿Cuál es el mejor enfoque para bloquear el hilo principal de la makeKeyAndOrderFront: ... método? Es este el enfoque correcto para la implementación de un controlador de finalización utilizando bloques?

¿Fue útil?

Solución

Su línea

_handler=[handler retain];

debería ser

_handler=[handler copy];

Esto debería resolver su problema, que las variables locales se han ido antes de que el controlador de finalización se llama. [handler copy] se encarga de las variables locales que se refiere el bloque, por lo que las variables locales no desaparecen incluso después de que el flujo del programa salió del método en la que hizo el bloque.

Recuerde los siguientes hechos:

  1. Las capturas instancia del bloque de las variables locales que se refiere el interior del bloque.
  2. Sin embargo, la instancia de bloque está en la pila. Que va a desaparecer incluso lo retienen, cuando el flujo del programa salir de la {...} ámbito en el que se crea el bloque.
  3. Por lo tanto, es necesario que copy, no sólo retain, si desea utilizar los datos después, como lo están haciendo aquí. Copying automáticamente retains todas las variables objeto local que se refiere a partir del bloque.
  4. Es necesario release una vez que haya terminado con él. Se desasigna la memoria para el propio bloque, y envía el mensaje release al objeto local de las variables que se refiere. Si utiliza GC, usted no tiene que preocuparse por esto, sin embargo.

Para entender más detalles de la cuadra, he encontrado el artículo aquí por Mike Ash muy útiles.

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