每次都不会触发委托函数audioPlayerDidFinishPlaying

时间:2012-11-19 22:00:06

标签: iphone xcode ipad avaudioplayer

我喜欢应用程序的键盘,我将每个新的AVAudioPlayer添加到NSMutableArray,这样我就能叠加声音。 我的问题是,那个delagate功能

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
如果在短间隔内有击键,则不会触发

。如果我以0.5秒或更长的间隔行程,一切正常。知道为什么吗? 我希望释放内存并在声音播放结束后从数组中删除对象。

更新

·H

@interface .. <AVAudioPlayerDelegate>
{
    NSMutableArray *soundObjects;
}

@property (nonatomic,strong) AVAudioPlayer *audioPlayer;

的.m

-(void)playSound {

    //
    //  play sound
    //

    _audioPlayer = [self loadWav:_soundID];
    _audioPlayer.delegate = self;

    [soundObjects addObject:_audioPlayer];
    AVAudioPlayer *temp = [soundObjects objectAtIndex:soundIndex];
    soundIndex = [soundObjects count];
    [temp play];
}

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
#ifdef DEBUG_SOUND
        NSLog(@"FLAG");
        soundIndex--;
        [soundObjects removeObjectAtIndex:soundIndex];
#endif
}

- (AVAudioPlayer *)loadWav:(NSString *)filename {
    NSURL * url = [[NSBundle mainBundle] URLForResource:filename withExtension:@"mp3"];
    NSError * error;

    AVAudioPlayer * player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];

    if (!player) {
#ifdef DEBUG_MODE
        NSLog(@"Error loading %@: %@", url, error.localizedDescription);
#endif
    } else {
        [player prepareToPlay];
    }
    return player;
}

2 个答案:

答案 0 :(得分:0)

尝试在后台进程中触发播放。这是我的第一次,但在不知道更多具体细节的情况下,我只能推测你是如何演奏声音的。如果您正在主线程上播放声音,那么同时在同一线程上缓冲和触发声音时,主线程上的键盘也将无响应。在处理媒体时,您通常应加载它并将其从主线程中播放,以消除竞争条件的可能性。如果将图像加载到歌曲或电影中,它通常不应该在主线程上,因为UI将无响应。

答案 1 :(得分:0)

在开发人员文档中有几个NSQueue的例子,我将使用我用自己的工作整理的Obj C Recipe书中的改编。

//This method detatches the instruction from the main thread
-(void)keyStrokeSelector:(NSString*)objectSound{


       [NSThread detachNewThreadSelector:@selector(keyStroke:objectSound)
                                toTarget:self
                              withObject:nil];


 }

//this selector will acctually execute the task
-(void)keyStroke:(NSString *)objectSound
{
   @autoreleasepool {
      //code to play the sound
   }
}

我希望这会有所帮助。关于上面代码的一些注意事项:你必须为每个单独的线程使用自动释放池,否则引用计数(MRC或ARC)将无法工作,因为它只能在自动释放池中工作,在主线程的线程中发生的代码应该被编码像其他任何东西一样,它只会执行并运行完成。如果您在子线程中有一个无限循环,那么在测试您的应用程序时可能不会引起注意,但是如果我正确记住了后台线程的当前最大时间,操作系统将在十分钟后终止应用程序。更重要的是,如果你没有创建一个特定于@autoreleasepool的线程那么我就不能强调这一点,那么即使你没有在新线程中创建一个新对象,当它们被传入时你的对象也不会被释放并且会占用内存占用量。他们将获得保留计数并留在记忆中。

我希望这会对您的计划有所帮助