使用 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()
这似乎成功了。
感谢那些做出回应的人 - 您对多线程的指导很有帮助。
我在 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()
这似乎成功了。
感谢那些做出回应的人 - 您对多线程的指导很有帮助。