Swift - 如何在不让应用程序挂起的情况下等待某些事情

Swift - How to wait for something without making the app hanging

我有这样的代码:

    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)
    }

它实际上在后台工作,从文件中读取工作和记录工作,但由于 GUI 将挂起执行一个快速完成任务的 while 循环,图像和文本更改将不可见。

searchForLogError 的代码是:

func searchLogForError(scriptPath:String) {
    if((readFile(path:logfilePath)!.filter { [=12=].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 { [=12=].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
    }
}

如何在不使用挂起 GUI 的情况下不断寻找日志文件更改的同时实现 NSImage 和 NSLocalizedString 的可见更改(或者甚至使用挂起 GUI,但有足够的时间更改 while 循环之间的可见元素) ?

轮询文件系统资源是一种糟糕的做法。 不要那样做。有专门的 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
}