在Swift中JSONDecoder解码大型对象时更新进度条 [英] Update a progress bar while JSONDecoder is decoding a huge object, in Swift

查看:94
本文介绍了在Swift中JSONDecoder解码大型对象时更新进度条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在像这样解码几GB的JSON编码数据

I'm decoding several gigabytes of JSON encoded data like this

let decoder = JSONDecoder()
let table = try decoder.decode([LogRow].self, from: content!)

其中 content 是纯文本。现在,此操作可能要花费几分钟,具体取决于内容的大小,我想显示一些进展。这是一个命令行程序,因此即使定期更新 table 的长度也已足够。问题是我看不到回调之类的东西。我尝试了一个比较笨拙的 Timer

where content is plain text. Now, this operation can take several minutes, depending on the size of content, and I'd like to show some kind of progress. This is a command line program, so even a periodic update on the length of table would be enough. The problem is that I don't see anything like a callback or something like that. I tried with a rather awkward Timer like this

var table: [LogRow]? = []
let timer = Timer(fire: Date(), interval: 1.0, repeats: true) { t in
    print("\(table?.count ?? 0) rows parsed.")
}
timer.fire()
table = try decoder.decode([LogRow].self, from: content!)
timer.invalidate()

但这只能运行一次-是因为解码器阻塞了主线程,而我正在运行计时器同一线程?我对GCD有点陌生,所以我不确定如何使用 DispatchQueue 来实现。

but that only runs once -- is it because the decoder blocks the main thread and I'm running the timer in the same thread? I'm a bit of a noob with the GCD so I'm not sure how to go about using a DispatchQueue for this.

有什么想法吗?

推荐答案

然后可以声明您的计时器,例如:

Then can declare your timer like:

    let timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.updateUI), userInfo: nil, repeats: true)
    DispatchQueue.global(qos: .background).async {
        self.perform(#selector(self.decode), on: Thread.current, with: nil, waitUntilDone: true)
        timer.invalidate()
    }

这意味着您想触发 updateUI 每秒执行一次操作。然后,您开始在后台线程中解码,并等待直到完成,然后再使计时器无效。

which means you want to trigger the updateUI action every second. Then you start to decode in a background thread and wait until done before invalidate your timer.

var totalDuration: Int = 0

@objc func updateUI () {
    self.currentDuration += 1
    print("------------> \(self.currentDuration)")
}

@objc func decode () {
    table = try decoder?.decode([LogRow].self, from: content!)
}

我添加了一个 currentDuration 变量,该变量可用于您的progressBar。但是,如果您需要向用户显示百分比,则必须知道总持续时间。

I added a currentDuration variable which could be used in your progressBar. But you must know the total duration if you need to show a percentage to your user.

这篇关于在Swift中JSONDecoder解码大型对象时更新进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆