在Swift中JSONDecoder解码大型对象时更新进度条 [英] Update a progress bar while JSONDecoder is decoding a huge object, in Swift
问题描述
我正在像这样解码几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屋!