У меня проблемы с обновлением пользовательского интерфейса из основного потока в моем приложении.
У меня есть следующий код.В качестве краткого описания я хочу, чтобы цикл for повторялся один раз каждые A секунд, но я хочу, чтобы вложенный асинхронный блок начинался через B секунд после начала каждой итерации.
public func startRecording()
{
let recordingPeriod = TimeInterval(Float(Constants.windowSize)/Float(Constants.sampleFrequency))
DispatchQueue.global().async // (1)
{
repeat
{
for (index, audioRecorder) in self.AudioRecorders.enumerated()
{
guard let audioRecorder = audioRecorder else { continue }
audioRecorder.deleteRecording()
audioRecorder.record()
DispatchQueue.main.asyncAfter(deadline: .now() + recordingPeriod) // (2)
{
if let pitch = self.finishSampling(audioRecorder: audioRecorder, index: self.AudioRecorders.index(of: audioRecorder))
{
print(pitch)
self.meterViewController?.updateMeter(string: String(pitch)) // (3)
}
}
// Use usleep here to pause thread which runs overall repeat loop
// Sets functional time interval for one loop iteration
usleep(useconds_t((Float(Constants.windowSize)/Float(Constants.samplesPerWindow))/Float(Constants.sampleFrequency)*1000000))
}
}
while self.keepRecording ?? false
}
}
Где (3) просто обновляет UILabel:
func updateMeter(string: String)
{
if Thread.isMainThread {
meterLabel.text = string
} else {
DispatchQueue.main.sync {
meterLabel.text = string
}
}
}
Похоже, что оператор if Thread.isMainThread
всегда возвращает true, как и ожидалось.Однако фактическое значение UILabel обновляется только для некоторых значений recordingPeriod
.После изменения значения recordingPeriod
UILabel либо обновляется по назначению, либо никогда не изменяется.Это кажется мне поведением, которое происходит при обновлении пользовательского интерфейса в фоновом потоке.
recordingPeriod
всегда достаточно длинный, чтобы UILabel успел обновить;он обновляется не чаще, чем несколько раз в секунду.
В качестве отступления, если я изменю (1) и (2) на оба вызова, то вызову DispatchQueue.main.
вместо (1) кода DispatchQueue.global()
, кодвнутри блока (2), кажется, никогда не работает.Разве не все блоки должны быть помещены в основную очередь и выполняться в какой-то момент?