0

免责声明:我对 iOS 编程比较陌生,并且我正在尝试自学基础知识,只是为了好玩……所以要温柔:-)


我正在构建一个应用程序,它可以播放一系列使用 AVAudioplayer 串在一起的 .mp3 文件。到目前为止,该部分运行良好。IBActions 和 IBOutlets 连接起来。点击按钮,播放音频。

我的问题是:我的播放按钮已直接添加到 main.storyboard,设置和自定义,其初始状态在 In​​terface Builder 中定义。当我单击播放时,我想更改按钮的图像以指示它正在播放。然而,一旦音频开始,看起来视图似乎是......暂停,或什么的。按钮图像保持不变,直到音频播放完毕。只有这样,按钮图像才会自行更新——几乎没有用处。

我也刚刚尝试设置另一个未附加到此特定按钮的随机 UIImageView 的图像。同样的经历。一旦我注释掉我的 playAudioArray 方法,按钮交换就会立即起作用。


    -(IBAction)start_playing:(UIButton*)pressed_button {
    [_btn_start setImage:[UIImage imageNamed:@"btn_on-active"] forState:UIControlStateNormal];

    [self playAudioArray];
    }

我希望我已经留下了足够的继续...任何想法/意见/建议?

谢谢一百万 - 德鲁

#

更新:

我发现当我将音频播放器放在 lopp 中时,更新视图会失败。此代码工作正常...


    if (audioPlayer.playing == YES) {

[audioPlayer pause];
[sender setImage:[UIImage imageNamed:@"btn_on.png"] forState:UIControlStateNormal];
[_btn_stop setImage:[UIImage imageNamed:@"btn_off.png"] forState:UIControlStateNormal];

} else {

NSString *path = [[NSBundle mainBundle] pathForResource:@"audio_file1" ofType:@"mp3"];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
audioPlayer.volume = 1.0;
audioPlayer.numberOfLoops = 0;
[audioPlayer setMeteringEnabled: YES];
[audioPlayer play];


//changes the image when the button is pressed
[sender setImage:[UIImage imageNamed:@"btn_on.png"] forState:UIControlStateNormal];
[_btn_stop setImage:[UIImage imageNamed:@"btn_off.png"] forState:UIControlStateNormal];

}

但是这段代码没有下面没有。


    } else {

//changes the image when the button is pressed
[sender setImage:[UIImage imageNamed:@"btn_on.png"] forState:UIControlStateNormal];
[_btn_stop setImage:[UIImage imageNamed:@"btn_off.png"] forState:UIControlStateNormal];

NSArray  *theSoundArray = [NSArray arrayWithObjects:@"audio1",@"audio2",@"audio3",nil];

for (int i = 0; i < totalSoundsInQueue;) {

NSString *sound = [theSoundArray objectAtIndex:i];

// Wait until the audio player is not playing anything
while(![audioPlayer isPlaying]){

NSString *path = [[NSBundle mainBundle] pathForResource:@"mom" ofType:@"mp3"];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
audioPlayer.volume = 1.0;
audioPlayer.numberOfLoops = 0;
[audioPlayer setMeteringEnabled: YES];
[audioPlayer play];

i++;

}        

}

}

音频播放正常,循环播放我所有的声音,没有出现错误。只是,我的按钮的“开启状态”只有在循环播放完成后才会设置。我已经尝试过许多不同类型的循环方法。For, for each, while...每次我开始循环播放声音时,音频播放效果很好,但显示失去了所有焦点。

这使我想起。一旦我进入循环,我的“停止”按钮就会失去它的可点击(可点击)性质。直到循环完成运行。如果我不在循环中,停止按钮可以正常工作,没有问题。

抱歉,如果我在这里犯了一个完全的新手错误……有人想/评论吗?

4

1 回答 1

0

for loop正在占用主线程,使其 UI 无响应。不要连续运行 for 循环,而是将自己设置为 AVAudioPlayer 的代表。一旦音频播放器完成播放,它将向委托发送消息- (void) audioPlayerDidReachEnd;(您必须实现)。然后您可以在该实现中播放队列中的下一个音频文件。无论如何,您真的想将自己设置为代表。AVAudioPlayer 将发送您的代理消息以处理中断(如来电)和解码错误。您想优雅地处理这些事件。

我认为音频播放良好的原因是它具有更高的优先级并在单独的线程上运行。UI 变得无响应的原因是即使动画/UI 更改发生在单独的线程上,它们也是从主线程启动的。但是所有 UI 更改都排队到运行循环的末尾(因此可以进行优化)。但是,该运行循环永远不会结束,因为for loop在播放所有音频文件之前,您永远不会结束。音频文件可以按顺序播放,因为它们是在其中启动for loop并在单独的线程上运行的。说得通?一般来说,你真的不想占用主线程。

于 2012-05-04T14:27:44.703 回答