Swift - Как ждать чего-то, не заставляя приложение зависать - PullRequest
0 голосов
/ 24 июня 2019

У меня есть такой код:

    print("Migration Execution: Successfully uninstalled MCAfee")
    migrationInfoPicture.image = NSImage(named: "Unroll")
    migrationInfoText.stringValue = NSLocalizedString("Unrolling from old server... Please wait!", comment: "Unrolling")
    while(!readFile(path:logfilePath)!.contains("result: 2 OK")) {
        searchLogForError(scriptPath: scriptOnePath)
    }
    print("Migration Execution: Successfully unrolled from old server")
    migrationInfoText.stringValue = NSLocalizedString("Setting up MDM profile... Please wait!", comment: "Setting up MDM")
    while(!readFile(path:logfilePath)!.contains("result: 3 OK")) {
        searchLogForError(scriptPath: scriptOnePath)
    }

На самом деле он работает в фоновом режиме, чтение из файла работает, а регистрация ведется, но поскольку графический интерфейс будет зависать при выполнении цикла while с быстро выполненной задачей, изменения изображения и текста не будут видны.

Код для searchForLogError:

func searchLogForError(scriptPath:String) {
    if((readFile(path:logfilePath)!.filter { $0.contains("ERROR") }).contains("ERROR")) {
        print("Migration abborted")
        migrationInfoPicture.image = NSImage(named: "FatalError")
        migrationInfoText.stringValue = NSLocalizedString("An error occured: \n", comment: "Error occurence") + readFile(path:logfilePath)!.filter { $0.contains("ERROR") }[0]
        migrationWarningText.stringValue = NSLocalizedString("In order to get further help, please contact: mac.workplace@swisscom.com", comment: "Error support information")
        self.view.window?.level = .normal
        btnExitApplicationOutlet.isHidden = false
        getScriptProcess(path:scriptPath).terminate()
        return
    }
}

Как я могу добиться видимого изменения NSImage и NSLocalizedString при постоянном поиске изменений файла журнала без зависания GUI (или даже с зависанием GUI, но с достаточным временем для изменения видимых элементов между циклами while)?

1 Ответ

1 голос
/ 24 июня 2019

Опрос ресурсов файловой системы - ужасная практика. Не делай этого .Существуют специальные API для наблюдения ресурсов файловой системы, например DispatchSourceFileSystemObject

Создание свойства

var fileSystemObject : DispatchSourceFileSystemObject?

и два метода для запуска и остановки наблюдателя.При закрытии setEventHandler введите код для чтения файла

func startObserver(at url: URL)
{
    if fileSystemObject != nil { return }

    let fileDescriptor : CInt = open(url.path, O_EVTONLY);
    if fileDescriptor < 0  {
        print("Could not open file descriptor"))
        return
    }
    fileSystemObject = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fileDescriptor, eventMask: [.write, .rename], queue: .global())

    if fileSystemObject == nil {
        close(fileDescriptor)
        print"Could not create Dispatch Source"))
        return
    }
    fileSystemObject!.setEventHandler {
        if self.fileSystemObject!.mask.contains(.write) {
           // the file has been modified, do something

        }
    }
    fileSystemObject!.setCancelHandler {
        close(fileDescriptor)
    }
    fileSystemObject!.resume()
}

func stopObserver()
{
   fileSystemObject?.cancel()
   fileSystemObject = nil
}
...