-1

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

我已经在类中声明了一个函数来更新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?

任何意见或指导,感激地收到。我一直无法找到任何相关的以前的问题。

+0

解析后台线程上的JSON并更新主线程上的文本视图。 – Willeke

+0

谢谢 - 那超出了我。所以一些研究和我会回报。 – Wolfstar

+0

我不明白为什么问题已被标记。有人能告诉我为什么这样我可以学习。 – Wolfstar

回答

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

这似乎已经做到了。

感谢那些已经回复的人 - 您对多线程的指导很有帮助。

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") 
    } 
} 
+0

嗨埃德蒙 - 这似乎并没有奏效。我在DispatchQueue.main.async中封装了self.addLogToConsoleWindow(newLogEntry:“正在解析的停靠事件”)语句,并且它的行为没有任何区别 – Wolfstar

+0

对此不以为然。需要查看完整的代码来找到真正的问题。 –

+1

我会继续努力,看看我能否先解决它。最好的学习方式。 – Wolfstar