Frage

Ich bin fest!

Ich versuche, eine benutzerdefinierte modalen Dialog zu erstellen. Ich möchte es in ähnlicher Weise einen Block als Abschluss-Handler zum NSSavePanel auszuführen verwendet wird.

Ich habe nur die wichtigen Schnipsel kopiert Ich denke, benötigt werden.

@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

Jetzt kann ich nennen dies den Code mit:

[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");

Alles geht gut, aber nach der Methode makeKeyAndOrderFront: modalToWindow: sourceRect: completionHandler: beendet es nicht den Faden nicht blockiert, so „Errg“ gedruckt wird, auch wenn der Benutzer nicht ausgewählt „ok“ hat oder „Abbrechen“. Das modale Fenster wird an dieser Stelle angezeigt, wo der Benutzer klickt auf OK und der _handler Block wird dann ausgeführt. Allerdings, wenn ich die Zugriff auf lokale Variablen im Block versuchen, und die App abstürzt, da alles bereits aufgeräumt hat.

Was ist der beste Ansatz, um den Haupt-Thread aus dem makeKeyAndOrderFront zu blockieren: ... Methode? Ist das der richtige Ansatz einen Abschluss Handler Blöcke zu implementieren?

War es hilfreich?

Lösung

Ihre Zeile

_handler=[handler retain];

sollte

_handler=[handler copy];

Das sollte Ihr Problem lösen, dass die lokalen Variablen verschwunden sind, bevor der Abschluss-Handler aufgerufen wird. [handler copy] kümmert sich um die lokalen Variablen auf die in den Block, so dass die lokalen Variablen gehen nicht weg, selbst nachdem der Ablauf des Programms, das Verfahren verlassen, wo Sie den Block aus.

Beachten Sie die folgenden Fakten:

  1. Die Blockinstanz erfasst die lokalen Variablen innerhalb des Blocks bezeichnet.
  2. ist jedoch die Block-Instanz auf dem Stapel. Es wird weggehen auch Sie es behalten, wenn der Ablauf des Programms geht aus dem Rahmen {...} in dem Sie den Baustein erstellen.
  3. Sie müssen also, um es copy, nicht nur retain es, wenn Sie die Daten später verwenden möchten, wie Sie hier tun. Copying es automatisch retains alle lokalen Objektvariablen indirekten Verweisen auf den Block.
  4. Sie müssen es release, wenn Sie mit ihm fertig sind. Es freigibt den Speicher für den Block selbst und sendet release Nachricht an den lokalen Objektvariablen bezeichnet. Wenn Sie GC verwenden, müssen Sie nicht darüber sorgen haben, though.

Für weitere Details des Blocks zu verstehen, fand ich den Artikel hier von Mike Ash sehr hilfreich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top