使用DispatchQueue修复从switch语句

时间:2017-06-02 09:18:56

标签: swift multithreading macos grand-central-dispatch nstextview

我在Swift 3(Xcode 8.3.2)中使用switch语句来解析macOS应用程序的一系列JSON对象(使用SwiftyJSON)。对于每种情况,我都尝试打印对同一类(NSViewController)中声明的textView的更新,并使用@IBOutlet绑定到相关的故事板中。

我在类中声明了一个函数来更新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 {}循环完成后更新,这意味着同时出现数千个文本行,而不是逐渐运行。

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

感激地收到任何建议或指导。我一直无法找到任何相关的问题。

2 个答案:

答案 0 :(得分:1)

正如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")
    }
}

答案 1 :(得分:0)

对于那些感兴趣的人,我解决了阅读此回复后我遇到的行为问题(DispatchQueue.main.sync returning exc_bad_instruction Swift 3

我对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()

这似乎已经成功了。

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