异步添加大量数据时,NSTextView 冻结了我的应用程序

NSTextView freezing my app when adding a lot of data asyncronously

我正在构建一个简单的 talker/listener 应用程序,它通过 UDP 接收 OSC 数据。我正在使用 OSCKit pod,它本身使用 CocoaAsyncSocket 库进行内部 UDP 通信。 当我正在监听一个特定端口以从另一个支持 OSC 的软件接收数据时,我将接收到的命令记录到 NSTextView。问题是有时,我会在很短的时间内收到数千条消息(编辑:我刚刚添加了一个计数器来查看我收到了多少消息。我在短短几秒钟内收到了超过 14000 条消息那只是我软件中的一个移动物体)。无法预测何时会发生这种情况,因此我无法锁定 NSTextViewtextStorage 对象以阻止它发送所有通知来更新 UI。通过委托回调函数处理数据。
那么您将如何绕过该限制?

   ///Handle incoming OSC messages
   func handle(_ message: OSCMessage!) {

      print("OSC Message: \(message)")

      let targetPath = message.address
      let args = message.arguments

      let msgAsString = "Path: \"\(targetPath)\"\nArguments: \n\(args)\n\n"
      print(msgAsString)
      oscLogView.string?.append(msgAsString)
      oscLogView.scrollToEndOfDocument(self)
   }

正如您在此处看到的(这是回调函数),每次收到消息时,我都会直接从回调中更新 TextView(添加数据和滚动到末尾)。这是 Instruments 告诉我减速发生的地方,附加是最慢的。我在分析中没有比这更进一步,但这肯定是由于它试图进行可视化更新,这比解析 32 位数据需要更多的时间,并且当它完成时它会收到另一个更新权远离服务器缓冲区。

我可以将该调用发送到后台线程吗?我不觉得用视觉更新填充后台线程是个好主意。也许我自己生成字符串缓冲区并时不时地使用计时器将其刷新到 TextView?

我想给它一个控制台的感觉,但是冻结的控制台不是控制台。

这里是link到project on github。 pods 都在那里并配置了 cocoapods,所以只需打开工作区即可。你们可能没有任何东西可以产生那么多的 OSC 流量,但如果你真的想深入挖掘,你可以得到 IanniX,它是一个开源 sequencer/trajectory 自动化程序,可以生成 OSC 和很多 OSC。我刚刚下载了它,我将构建一个快速项目,该项目应该发送足够的数据来冻结应用程序,如果有人想试一试,我会把它添加到存储库中。

我将传入数据附加到一个缓冲区变量,并使用一个计时器每 0.2 秒将该缓冲区刷新到 textview。 textview 的更新周期太慢,无法处理传入的数据量,因此将网络回调卸载到计时器让服务器处理数据,而不是每 32 位停止一次。

如果有人想出更优雅的方法,我很开放。