UILabel не обновляется последовательно - PullRequest
0 голосов
/ 10 января 2019

У меня очень простой метод обновления, в который я включил строки отладки.

@IBOutlet weak var meterLabel: UILabel!

func updateMeter(string: String)
{
    if Thread.isMainThread {
        meterLabel.text = string
    } else {
        DispatchQueue.main.sync {
            meterLabel.text = string
        }
    }
    print(string)
}

Очевидно, string никогда не ноль. Функция updateMeter вызывается примерно 3 раза в секунду, однако в настоящее время в симуляторе я не вижу изменения UILabel (оно меняется во время вызовов этого же updateMeter в другом месте). Есть ли причина, по которой изменение текста UILabel не привело бы к видимым результатам в главном потоке?

Вызывается здесь:

public func startRecording()
{
    let recordingPeriod = TimeInterval(Float(Constants.windowSize)/Float(Constants.sampleFrequency))
    var index = 0
    Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
        let audioRecorder = self.AudioRecorders[index]!
        audioRecorder.deleteRecording()
        audioRecorder.record()
        DispatchQueue.main.asyncAfter(deadline: .now() + recordingPeriod)
        {
            if let pitch = self.finishSampling(audioRecorder: audioRecorder, index: self.AudioRecorders.index(of: audioRecorder))
            {
                self.meterViewController?.updateMeter(string: String(pitch))
            }
        }
        index = index + 1
        if index == 4 { index = 0 }
        if !(self.keepRecording ?? false) { timer.invalidate() }
    }
}

Другие методы, называемые:

private func finishSampling(audioRecorder: AVAudioRecorder?, index: Int?) -> Float?
{
    audioRecorder?.stop()
    if let index = index, var (data, _, _) = loadAudioSignal(audioURL: getDirectory(for: index))
    {
        let pitch = getPitch(&data, Int32(data.count), Int32(Constants.windowSize), Int32(Constants.sampleFrequency))
        return Float(pitch)
    }
    return nil
}

private func loadAudioSignal(audioURL: URL) -> (signal: [Float], rate: Double, frameCount: Int)?
{
    guard
        let file = try? AVAudioFile(forReading: audioURL),
        let format = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: file.fileFormat.sampleRate, channels: file.fileFormat.channelCount, interleaved: false),
        let buf = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: UInt32(file.length))
        else
    {
        return nil
    }
    try? file.read(into: buf)
    let floatArray = Array(UnsafeBufferPointer(start: buf.floatChannelData?[0], count:Int(buf.frameLength)))
    return (signal: floatArray, rate: file.fileFormat.sampleRate, frameCount: Int(file.length))
}

Где getPitch выполняет простую обработку и выполняется относительно быстро.

1 Ответ

0 голосов
/ 10 января 2019

Вызывая usleep, вы блокируете основной поток. Основной поток - это поток, который обновляет пользовательский интерфейс. Поскольку он заблокирован, он не может этого сделать.

Вы должны использовать альтернативный подход, например Timer, для периодического обновления метки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...