从installTapOnBus闭包中访问类属性

时间:2016-01-19 19:10:48

标签: ios swift core-audio avaudioengine

我有一个非常简单的self.meter.text="..." let inputNode = audioEngine.inputNode let bus = 0 inputNode!.installTapOnBus(bus, bufferSize: 2048, format: inputNode!.inputFormatForBus(bus)) { (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in var someFeature:Float=0.0 for var i=0; i<Int(buffer.frameLength); i += 1{ someFeature += fabs(buffer.floatChannelData.memory[i]) } someFeature /= Float(buffer.frameLength) self.meter.text="\(someFeature)" // No effect! print("\(someFeature)") // This works } 闭包成功更新控制台,但不是UI元素。这是代码:

self

也许我需要向闭包发送对{{1}}的弱引用,但我不确定语法。关于如何更新UI元素的任何反馈/想法都会很棒!谢谢你的阅读。

2 个答案:

答案 0 :(得分:1)

解决方案似乎是在主线程上调用self.meter.text = ...

dispatch_async(dispatch_get_main_queue()) { 
    self.meter.text="\(someFeature)"
}

如果有人可以填写有关此内容的详细信息,我会在一两天内不加检查这个答案。

答案 1 :(得分:1)

您应该只从主线程进行UIKit调用。

来自UIView的documentation

  

线程注意事项

     

必须在主线程上对应用程序的用户界面进行操作。因此,您应该始终从应用程序主线程中运行的代码调用UIView类的方法。这可能不是绝对必要的唯一时间是创建视图对象本身,但所有其他操作应该在主线程上发生。

如果您查看AVAudioNode的API参考,特别是installTapOnBus

  

可以在主线程以外的线程上调用tapBlock。

您的用户界面没有更新,因为来自inputNode!.installTapOnBus()的回调正在后台线程上执行,而您正在尝试从此线程更新用户界面。

正如您所发现的,您将希望通过以下方式从主线程进行UI调用:

dispatch_async(dispatch_get_main_queue(), ^{
   /* Make UIKit calls here */
});