NSOpenPanel (beginWithCompletionHandler:) Misserfolg

Dylans Ghost

Dylans Ghost

Aktives Mitglied
Thread Starter
Dabei seit
25.09.2012
Beiträge
110
Reaktionspunkte
2
Hallo,
ich kenn' mich mit Blocks nicht aus, kann darum nicht feststellen, was da schief läuft.
Brauche ich vielleicht eine Deklaration und wenn - wie sieht die aus ?
Code:
-(NSMutableDictionary*)openWavePanel
{
    __block NSMutableDictionary * dictionary;
    NSOpenPanel * panel = [NSOpenPanel openPanel];
    [panel setCanChooseDirectories:NO];
    [panel setCanChooseFiles:YES];
    [panel setAllowsMultipleSelection:NO];
    [panel beginWithCompletionHandler:^(NSInteger result) // Hier Sprung zum return.
    {
        if (result == NSFileHandlingPanelOKButton)
        {
            NSURL*  url = [[panel URLs] objectAtIndex:0];
            dictionary = [self loadDataFromURL:url];
        }
    }];
    return dictionary;
}

Grüsse
Uwe
 
Hallo,

der Block wird asynchron aufgerufen.
D.h. Du musst Dein Design ändern, den Dein return-Wert kann nichts liefern.

Zu dem hast Du einen "großen Fehler" in Deinem Code.
Du musst Dein dictionary auf nil setzen.
Lokale Variablen müssen genullt werden, da sie sonst auf beliebige Instanzen zeigen können und Du mit dubiosen Verhalten konfrontierst wirst.

Spätestens bei NSError wirst Du schauen, wenn es mal geht und mal nicht.

Viele Grüße
 
Das ist so schon richtig, der Block wird später asynchron ausgeführt. Das bedeutet dass dein Dictionary bzw. nil sofort zurück gegeben wird und erst später, wenn der Completion Handler ausgeführt wird, gefüllt wird. Du solltest den Code so umbauen, dass du entweder aus dem Block eine Methode aufrufst, der du das Dictionary übergibst (Achtung auf dem Main Thread ausführen!) oder du arbeitest mit Notifications bzw. KVO.
 
  • Gefällt mir
Reaktionen: Dylans Ghost
Wir wissen ja nicht wie seine Umgebung aussieht.
Deshalb gehe ich mal nicht von ARC aus.

Ich weiß nicht wie andere Entwickler es handhaben, aber für mich gehört nil zum "guten Ton".

Viele Grüße
 
Da ARC mittlerweile so alt ist, würde ich davon ausgehen. Aber ich meine mich zu erinnern, dass auch ohne ARC lokale Variablen mit NULL initialisiert werden.
Wie auch immer, du hast natürlich recht, dass eine eigene Initialisierung mit einem 0-Wert wesentlich besser, sicherer und weniger fehlerträchtig ist.
 
Code:
-(void)openWavePanelAtWindow:(NSWindow*)window
{
    NSOpenPanel * panel = [NSOpenPanel openPanel];
    [panel setCanChooseDirectories:NO];
    [panel setCanChooseFiles:YES];
    [panel setAllowsMultipleSelection:NO];
    [panel beginSheetModalForWindow:window completionHandler:^(NSInteger result)
    {
        if (result == NSFileHandlingPanelOKButton)
        {
            NSURL*  url = [[panel URLs] objectAtIndex:0];
            [self loadDataFromURL:url];
        }
    }];

}
Code:
-(void)loadDataFromURL:(NSURL*)anURL
{
    NSData *data = [NSData dataWithContentsOfURL:anURL];
    NSMutableDictionary * root = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    if(root == nil)
    {
        NSBeep();
        printf("Failed to load data \n");
    }else  [_appDelegate setRootDictionary:root];
}
So funktioniert's, das dictionary ist nun leider fix.

Danke an euch, hab' was Wichtiges gelernt !
 
Zurück
Oben Unten