2016-06-02 18 views
1

Ich bin ein Neuling bei Swift (2.2) und habe ein Problem mit einer einfachen App mit Xcode 7.3 und OS X 10.11. In dieser App klickt der Benutzer auf eine Schaltfläche und wählt eine Datei über NSOpenPanel aus. Der Code verwendet die ausgewählte URL, um die Daten und den Namen der Datei abzurufen, verarbeitet die Daten und speichert das Ergebnis an einem anderen Ort. Bei großen Dateien kann die Verarbeitung einige Sekunden dauern. Bei der Verarbeitung großer Dateien bleibt der Bereich, in dem das Fenster "Datei öffnen" angezeigt wurde, nach dem Auswählen der Datei leer und deckt die App-Ansicht sowie alle anderen Elemente ab und bleibt dort, bis der Vorgang abgeschlossen ist. Außerdem sind die Verkaufsstellen der App bis zum Ende des Vorgangs eingefroren. Es scheint, dass NSOpenPanel die Fenstersteuerung nicht an die App und das System zurückgibt.NSOpenPanel wird während der Swift-Funktion nicht richtig geschlossen

Der Code lautet:

@IBAction func processFile(sender: AnyObject) { 
    var chosenURL: NSURL? 
    let openPanel = NSOpenPanel() 
    openPanel.title = "Choose a file" 
    openPanel.canChooseDirectories = false 
    openPanel.allowsMultipleSelection = false 

    if openPanel.runModal() == NSFileHandlingPanelOKButton { 
      chosenURL = openPanel.URL 
    } 
    let dataBytes = NSData(contentsOfURL: chosenURL!) 
    let fileName = chosenURL!.lastPathCompnent! 
    // Remaining code processes dataBytes and fileName 

Ich habe ein paar Variationen ausprobiert, aber das gleiche Ergebnis. Die Suche nach "NSOpenPanel wird nicht geschlossen" auf dem "Netzwerk" bringt normalerweise nur Beispiele in Objective-C, von denen ich nichts weiß. Irgendwelche Vorschläge, wie Sie NSOpenPanel ausschalten und die Ansicht und Steuerung zum App-Fenster zurückkehren lassen?

+0

'NSData (contentsOfURL: selectedURL!)' Dies blockiert Ihre Benutzeroberfläche. Sie sollten die Daten im Hintergrund erhalten. – Moritz

+0

Ich bin mir nicht sicher, was das bedeutet. Hat das mit GCD zu tun? – Micos

Antwort

1

Nach dem Vorschlag von Eric D'sah ich in Grand Central Dispatch und Hintergrundprozesse. Mein erster Ansatz war:

dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) { 
dataBytes = NSData(contentsOfURL: chosenURL!) 
} 

Das änderte nichts. Ich fand, dass ich den gesamten verbleibenden Prozess (alles von "let dataBytes ...") innerhalb der Dispatch-Schließung setzen musste, mit "dispatch_async (dispatch_get_main_queue())" Anweisungen über UI-Updates. Dadurch wurde das Fenster nicht mehr eingefroren und ausgeblendet und die Steuerung an die App zurückgegeben. Nochmals vielen Dank, Eric.