-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