我正在关注iOS“音频队列编程指南 - 播放音频”。在指南的末尾,步骤Start and Run an Audio Queue中有CFRunLoopRunInMode()
来电:
do { // 5
CFRunLoopRunInMode ( // 6
kCFRunLoopDefaultMode, // 7
0.25, // 8
false // 9
);
} while (aqData.mIsRunning);
//...
关于第6行的文档说: “CFRunLoopRunInMode函数运行包含音频队列线程的运行循环。” 但是,当我的方法返回时,是不是执行了运行循环?上面的代码是在我的应用程序中按下播放按钮时由主线程执行的。
现在我很难理解这些对CFRunLoopRunInMode()
的调用有什么好处,因为它们的缺点是我的播放按钮没有正确更新(它看起来整个时间都按下了音频播放)并没有积极的效果,即如果我从代码中删除do-while-loop以及调用CFRunLoopRunInMode()
并且直接从此方法返回,则音频也可以很好地播放。
那么这就指出了显而易见的解决方案,只需将这些调用删除,因为这不会产生问题。有人可以解释为什么Apple在使用iOS中的音频队列进行音频播放的官方指南中包含此代码吗?
编辑:
我刚才看到,在Mac OS X中,存在与iOS相同的音频队列API,iOS指南似乎是Mac OS guide的复制粘贴复制。这让我怀疑那些对运行循环的调用仅在Mac OS中需要而在iOS中不再需要,例如因为否则Mac OS应用程序会退出或类似的东西。有人可以验证这个或排除它吗?
答案 0 :(得分:1)
@bunnyhero是对的,CFRunLoopRunInMode()
通常用于命令行示例
只要您的AudioQueueRef
未被解除分配,您就不必在IOS中使用CFRunLoopRunInMode()
...
我所做的是为音频队列创建一个单独的类,只要我的类指针和AudioQueueRef
被分配,我就可以播放,暂停,恢复,停止等....
答案 1 :(得分:0)
与OP有关AQ阻止UI线程的问题有关,以进一步解放AQ用户免于盲目地复制that CoreAudio AQ example cited,
我还要补充一点,该示例将AQ配置为在Listing 3-11 Creating a playback audio queue
中的主线程的当前运行循环中运行:
AudioQueueNewOutput ( // 1
&aqData.mDataFormat, // 2
HandleOutputBuffer, // 3
&aqData, // 4
CFRunLoopGetCurrent (), // 5
kCFRunLoopCommonModes, // 6
0, // 7
&aqData.mQueue // 8
);
,请参见上面的参数值CFRunLoopGetCurrent ()
。文字说明
当前运行循环,以及在其上播放音频队列的循环 回调将被调用。
看一下函数原型:
OSStatus AudioQueueNewOutput(
const AudioStreamBasicDescription *inFormat, // 2
AudioQueueOutputCallback inCallbackProc, // 3
void *inUserData, // 4
CFRunLoopRef inCallbackRunLoop, // 5
CFStringRef inCallbackRunLoopMode, // 6
UInt32 inFlags, // 7
AudioQueueRef _Nullable *outAQ // 8
);
如果将{5替换为NULL
,则AQ将在CoreAudio内部线程中运行,从而对您的应用程序更加有效。
答案 2 :(得分:0)
CFRunLoopRunInMode
需要在代码执行结束时(例如,在运行终端应用程序时)使音频队列保持活动状态。 iOS应用程序包含生命周期:要使音频队列保持活动状态,只需声明AudioQueueRef
作为成员变量。否则,如果在方法范围内声明它,则在执行该方法后销毁它-因此,它将停止-除非您使用CFRunLoopRunInMode
使它保持活动状态。
总而言之,只要您将AudioQueueRef
或新的AVAudioEngine
的成员变量保存在没有从内存中释放出来的实例化类中,那么CFRunLoopRunInMode
就是不需要。