使用 DispatchQueue 修复从 switch 语句更新 NSTextView 的延迟

Using DispatchQueue to fix Delay in updating NSTextView from switch statement

我在 Swift 3 (Xcode 8.3.2) 中使用 switch 语句来解析一系列 JSON 对象(使用 SwiftyJSON) 对于 macOS 应用程序。对于每种情况,我都试图打印对在同一 class (NSViewController) 中声明并使用 @IBOutlet.

绑定在相关情节提要中的 textView 的更新

我在 class 中声明了一个函数来更新 textView 并使用我想打印到 textView 的相关文本调用该函数 (func addLogToConsoleWindow(newLogEntry: String) {})。

相关代码为:

    @IBOutlet var textViewActivityLog: NSTextView!  // Create an outlet for the activity log view

..............

        for jsonObj in arrayOfJSONObjects {
        if jsonObj != JSON.null {


            // Use a switch statement to select the correct Class to use for storing the appropriate event

            switch jsonObj["event"].string! {
            case "Docked":
                arrayOfDockedEvents.append(jsonObj)
                self.addLogToConsoleWindow(newLogEntry: "Docked event being parsed")
            case "FSDJump":
                arrayOfFSDJumpEvents.append(jsonObj)
                self.addLogToConsoleWindow(newLogEntry: "FSD Jump event being parsed")
            case "Progress":
                arrayOfProgressEvents.append(jsonObj)
                self.addLogToConsoleWindow(newLogEntry: "Commander's progress being parsed")
            case "Rank":
                arrayOfRankEvents.append(jsonObj)
                self.addLogToConsoleWindow(newLogEntry: "Rank information being parsed")
            case "LoadGame":
                arrayOfLoadGameEvents.append(jsonObj)
                self.addLogToConsoleWindow(newLogEntry: "Game load details being parsed")
            case "StartJump":
                arrayOfStartFSDJumps.append(jsonObj)
                self.addLogToConsoleWindow(newLogEntry: "Start FSD Jump event being parsed")
            case "MiningRefined":
                arrayOfMiningRefined.append(jsonObj)
                self.addLogToConsoleWindow(newLogEntry: "Mining event being parsed")
            default:
                if !setOfEventType.contains(jsonObj["event"].string!) {
                    self.addLogToConsoleWindow(newLogEntry: "\((jsonObj["event"].string!)) event discovered but not parsed")
                }
            }                
        } else {
            print("Haven't been able to find a jsonObj")
        }
    }  //  END OF 'for jsonObj'

............

    @objc func addLogToConsoleWindow(newLogEntry: String) {
         textViewActivityLog.string? = "\n" + newLogEntry + (textViewActivityLog.string)!
         textViewActivityLog.scrollRangeToVisible(NSMakeRange(0, 0))
} // END OF addLogToConsoleWindow()

我正在寻找的行为是在访问特定案例时立即更新 textView(textViewActivityLog.string?)。

但是,textView 不会立即更新。它仅在 for jsonObj in arrayOfJSONObjects {} 循环完成后更新,这意味着同时出现数千个文本行,而不是随着 for 循环运行逐渐出现。

如何在调用 func addLogToConsoleWindow(newLogEntry: String) {} 函数的代码中更新 textView?

非常感谢收到的任何建议或指导。我一直找不到任何相关的以前的问题。

正如 Willeke 所说,您可以这样做:

    switch jsonObj["event"].string! 
{
    case "Docked":
        arrayOfDockedEvents.append(jsonObj)
        self.addLogToConsoleWindow(newLogEntry: "Docked event being parsed")
    case "FSDJump":
        arrayOfFSDJumpEvents.append(jsonObj)
        self.addLogToConsoleWindow(newLogEntry: "FSD Jump event being parsed")

        //do on main thread...
        DispatchQueue.main.async
        {
            //updating text on label or other textview
        }

    case "Progress":
        arrayOfProgressEvents.append(jsonObj)
        self.addLogToConsoleWindow(newLogEntry: "Commander's progress being parsed")
    // ...
    default:
    if !setOfEventType.contains(jsonObj["event"].string!) 
    {
        self.addLogToConsoleWindow(newLogEntry: "\((jsonObj["event"].string!)) event discovered but not parsed")
    }
}

对于那些感兴趣的人,我解决了阅读此回复后遇到的行为问题 ()

我对 addLogToConsoleWindow(newLogEntry: String) {} 函数进行了以下更改:

    func addLogToConsoleWindow(newLogEntry: String) {
    DispatchQueue.global().async (execute: {
        DispatchQueue.main.sync {
            self.textViewActivityLog.string? = "\n" + ":->  " + newLogEntry + (self.textViewActivityLog.string)!
            self.textViewActivityLog.scrollRangeToVisible(NSMakeRange(0, 0))
        }
    })
} // END OF addLogToConsoleWindow()

这似乎成功了。

感谢那些做出回应的人 - 您对多线程的指导很有帮助。