-1

J'utilise une instruction switch dans Swift 3 (Xcode 8.3.2) pour analyser une plage d'objets JSON (en utilisant SwiftyJSON) pour une application macOS. Pour chaque cas j'essaye d'imprimer une mise à jour à un textView qui est déclaré dans la même classe (NSViewController) et lié dans le storyboard approprié en utilisant un @IBOutlet.Utilisation de DispatchQueue pour corriger Retard dans la mise à jour de NSTextView à partir de l'instruction switch

J'ai déclaré une fonction dans la classe pour mettre à jour le textView et appeler cette fonction (func addLogToConsoleWindow(newLogEntry: String) {}) avec le texte pertinent que je veux imprimer dans textView.

Le code correspondant est:

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

Le comportement que je cherche est d'avoir la textView (textViewActivityLog.string?) Mise à jour immédiatement quand le cas particulier est accédé.

Toutefois, textView ne se met pas à jour immédiatement. Il ne se met à jour qu'après la fin de la boucle for jsonObj in arrayOfJSONObjects {}, ce qui signifie que plus de plusieurs milliers de lignes de texte apparaissent en même temps plutôt que progressivement au fur et à mesure de l'exécution de la boucle for.

Comment puis-je obtenir la mise à jour de textView au point dans le code que la fonction func addLogToConsoleWindow(newLogEntry: String) {} est appelée?

Des conseils ou des recommandations ont été bien accueillis. J'ai été incapable de trouver des questions précédentes pertinentes.

+0

Analyser le JSON sur un thread d'arrière-plan et mettre à jour l'affichage de texte sur le thread principal. – Willeke

+0

Merci - c'est au-delà de moi. Donc quelques recherches et je ferai rapport. – Wolfstar

+0

Je ne comprends pas pourquoi la question a été balisée. Quelqu'un peut-il me conseiller pourquoi je peux apprendre. – Wolfstar

Répondre

0

Pour les intéressés, je l'ai résolu la question du comportement que j'avais après avoir lu cette réponse (DispatchQueue.main.sync returning exc_bad_instruction Swift 3)

J'ai fait ce qui suit modification de la fonction 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() 

qui semble avoir fait le tour.

Mes remerciements à ceux qui ont répondu - vos conseils en matière de multithreading ont été utiles.

1

Comme dit Willeke, vous pouvez faire quelque chose comme ça:

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

Salut Edmund - cela ne semble pas avoir fonctionné. J'ai encapsulé l'instruction self.addLogToConsoleWindow (newLogEntry: "Docked event being parsed") dans DispatchQueue.main.async et cela n'a fait aucune différence sur le comportement – Wolfstar

+0

Désolé d'avoir entendu cela. Besoin de voir le code complet pour localiser le vrai problème .. –

+1

Je vais continuer à travailler dessus et voir si je peux le résoudre en premier. meilleure façon d'apprendre. – Wolfstar