快速处理大量数据并使用队列正确显示

时间:2018-07-11 10:08:49

标签: ios swift queue grand-central-dispatch

我遇到了无法解决的线程问题。

private func addTextToOutputView(_ text: String){
    var t = text
    DispatchQueue.main.async {
        var recentText = self.outputTextView.text

        self.responseLogQueue.async {
            if let firstChar = t.first, let index = t.index(of: firstChar) {
                if firstChar == "\n" {
                    let subS = t[index...]
                    t = String(subS)
                }
            }
        }
        let currentTime = Date()
        let currentTimeString = self.dateFormatter.string(from: currentTime)
        t = "\n\(currentTimeString) \(t)"

        recentText?.append(t)

        self.outputTextView.text = recentText

        if self.isScenarioOuputRunning {
            if self.outputTextView.text.count > 0 {
                let bottom = NSMakeRange(self.outputTextView.text.count-1, 1)
                self.outputTextView.scrollRangeToVisible(bottom)
            }
        }
    }
}

连接到发送大量数据且快速的BLE设备。

我需要按到达顺序显示数据。

这项工作一直到这里的某个点时,当数据过多时,应用程序都会卡住。

我只是不知道如何设置它以获取已经显示的数据(需要在主队列上执行此操作?)然后对其进行操作(在我自己的后端队列上),然后显示为已连接数据再次显示在屏幕上(文本视图)。

如果我将其封装在全局队列(我的队列)中,然后仅在主队列中调用get和set部分,则我尝试的所有操作都不会这样做,这会丢失部分数据,并且这样,我可以正确获取所有数据,但拥有的大量数据使应用程序卡在某个特定点

有人看到这个问题吗?

令人不安的是,在OBJ-C中,相同的代码(逻辑-逐行)正好工作!

1 个答案:

答案 0 :(得分:1)

您编写的代码意义不大;您正在分派一些代码,这些代码将t更新到另一个队列,但是随后在当前线程中使用t来更新文本视图。另外,您分派到responseLogQueue上的代码可以有效地t = String(t)

我建议您不要将textview本身用作数据模型。它应该只是存储在string属性中的文本视图。您可以使用串行分派队列来更新此字符串属性,并使用计时器来定期刷新UI:

 class SomeViewController {

     var outputTextView: UITextView!

     private var refreshTimer: Timer?
     private var outputText = ""
     private var responseLogQueue: DispatchQueue!

     override func viewDidLoad() {
         super.viewDidLoad()
         self.responseLogQueue = DispatchQueue(label:"ResponseLogQueue")
         self.timer =  Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] (timer) in
            guard let strongSelf = self else {
                return
            }
            if self.isScenarioOuputRunning && !strongSelf.outputText.isEmpty {
                strongSelf.outputTextView.text = strongSelf.outputText
                let bottom = NSMakeRange(strongSelf.outputTextView.text.count-1, 1)
                strongSelf.outputTextView.scrollRangeToVisible(bottom)
            }
        })
    }

    private func addTextToOutputView(_ text: String) {
        let currentTimeString = self.dateFormatter.string(from: Date())
        let newText = "\n\(currentTimeString) \(text)"
        self.responseLogQueue.async {
            self.outputText = self.outputText.append(newText)
        }
    }
}