Benutzerdefinierte Modal Fenster mit Block-Completion-Handler
-
22-09-2019 - |
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?
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:
- Die Blockinstanz erfasst die lokalen Variablen innerhalb des Blocks bezeichnet.
- 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. - Sie müssen also, um es
copy
, nicht nurretain
es, wenn Sie die Daten später verwenden möchten, wie Sie hier tun.Copy
ing es automatischretain
s alle lokalen Objektvariablen indirekten Verweisen auf den Block. - Sie müssen es
release
, wenn Sie mit ihm fertig sind. Es freigibt den Speicher für den Block selbst und sendetrelease
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.