NSOpenPanel не будет закрываться должным образом во время функции Swift

Я новичок в Swift (2.2), и у меня проблема с простым приложением, использующим Xcode 7.3 и OS X 10.11. В этом приложении пользователь нажимает кнопку и выбирает файл через NSOpenPanel. Код использует выбранный URL-адрес для получения данных и имени файла, затем обрабатывает данные и сохраняет результат в другом месте. Для больших файлов обработка может занять несколько секунд. При обработке больших файлов после выбора файла место, где было окно «Открыть файл», остается пустым, закрывая вид приложения и все остальное, и остается там до завершения операции. Кроме того, выходы приложения замораживаются до завершения операции. Похоже, что NSOpenPanel не возвращает управление окном приложению и системе.

Код выглядит следующим образом:

@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  

Я пробовал несколько вариантов, но получил тот же результат. Поиск «NSOpenPanel не закроется» в сети обычно просто приводит примеры в Objective-C, о которых я ничего не знаю. Любые предложения о том, как отключить NSOpenPanel и вернуть просмотр и управление в окно приложения?


person Micos    schedule 02.06.2016    source источник
comment
NSData(contentsOfURL: chosenURL!) Это то, что блокирует ваш пользовательский интерфейс. Вы должны получить данные в фоновом режиме.   -  person Eric Aya    schedule 02.06.2016
comment
Я не уверен, что это значит. Это как-то связано с GCD?   -  person Micos    schedule 03.06.2016


Ответы (1)


Следуя предложению Эрика Д., я изучил Grand Central Dispatch и фоновые процессы. Мой первый подход был:

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

Это ничего не изменило. Я обнаружил, что мне пришлось поместить весь оставшийся процесс (все, начиная с «let dataBytes…») в закрытие отправки с операторами «dispatch_async(dispatch_get_main_queue())» вокруг обновлений пользовательского интерфейса. Это предотвратило зависание и гашение окна и вернуло управление приложению. Еще раз спасибо, Эрик.

person Micos    schedule 06.06.2016