AVAudioPlayer内存泄漏

8
我遇到了一个与AVAudioPlayer相关的奇怪内存泄漏问题,尝试了所有能想到的方法后仍需要帮助。
以下是问题的简要描述 - 代码紧随其后。 我初始化播放器并开始循环播放声音轨道(无限循环或一次播放均未改变问题)。几秒钟后,音乐开始播放,我切换到另一个声音轨道,因此我创建了一个新的播放器,初始化它,释放旧的播放器(正在播放),然后设置新的播放器并播放。
在此时(在调用新播放器-[Player play]之后),我会出现内存泄漏(3.5Kb)。
我尝试了以下操作:
- 停止旧播放器,然后释放它 - 没有效果 - 在播放指令后立即释放播放器 - 没有开始播放 - 两次释放旧播放器 - 崩溃 - 当我创建和播放第一个播放器时,没有发生内存泄漏!
此外,在参考文献中确实提到“播放”是异步的,因此可能会将引用计数增加1,但在这种情况下,为什么[Player stop]没有帮助呢?
谢谢,
以下是我如何使用它的代码的一些部分:
- (void) loadAndActivateAudioFunction {
NSBundle        *mainBundle = [NSBundle mainBundle];
NSError         *error;
NSURL           *audioURL = [NSURL fileURLWithPath:[mainBundle pathForResource: Name ofType: Type]];
AVAudioPlayer   *player = [(AVAudioPlayer*) [AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error];

if (!player) {
    DebugLog(@"Audio Load Error: no Player: %@", [error localizedDescription]);
    DuringAudioPrep = false;
    return;
}
[self lock];
[self setAudioPlayer: player];
[self ActivateAudioFunction];
[self unlock];

}

- (void) setAudioPlayer : (AVAudioPlayer *) player {
if (Player)
{
    if ([Player isPlaying] || Repeat)  // The indication was off???
        [Player stop];
    [Player release];
}
Player = player;

}

- (void) ActivateAudioFunction {
[Player setVolume: Volume];
[Player setNumberOfLoops: Repeat];    
[Player play];

DuringAudioPrep = false;

}

4个回答

8

以下是创建AVAudioPlayer的方法,可以避免内存泄漏。 点击此处了解更多信息

我在我的应用程序中进行了确认,这种方法完全消除了我的AVAudioPlayer内存泄漏问题。

- (AVAudioPlayer *)audioPlayerWithContentsOfFile:(NSString *)path {
    NSData *audioData = [NSData dataWithContentsOfFile:path];
    AVAudioPlayer *player = [AVAudioPlayer alloc];
    if([player initWithData:audioData error:NULL]) {
        [player autorelease];
    } else {
        [player release];
        player = nil;
    }
    return player;
}

这段代码真的很奇怪,没有理由将alloc和init调用分开。为了更好的通用方法,请参见http://stackoverflow.com/questions/17603551/arc-forbids-autorelease/17604365#17604365或者您可以像这样添加autorelease [[[AVAudioPlayer alloc] initWithData:audioData error:NULL] autorelease] - MoDJ

3

实现协议AVAudioPlayerDelegate及其方法audioPlayerDidFinishPlaying:successfully:,然后释放音频播放器对象。

例如:

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    [player release]; // releases the player object
}

0

就我所看到的,您的代码看起来很好,所以也许是其他地方的代码导致了问题。

我要说的是,您使用了一种有点奇怪的习语。与其在创建时保留,在设置时释放,我会这样做:

    // new players will always be created autoreleased.
    AVAudioPlayer   *player = [[(AVAudioPlayer*) [AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error] autorelease];

- (void) setAudioPlayer : (AVAudioPlayer *) player 
{
  if (Player)
  {
      if ([Player isPlaying] || Repeat)  // The indication was off???
            [Player stop];
        [Player release];
  }
  Player = [player retain];
}

这样做,只有在实际进入setAudioPlayer方法时才保留“player”对象,这可能会更容易追踪。

此外,请验证是否正在泄漏AVAudioPlayer对象。工具应该能够为您验证这一点。


谢谢你的回答。是的 - 我用Instruments验证了它是AVAudioPlayer。 至于方法 - 我使用这个方法是因为我实际上保存了不同的音轨,并通过匹配名称重复使用它们,如果它们没有播放(而不是多次下载相同的音轨)。由于我知道在对其进行“Alloc”后从调用者获取播放器,所以我知道它已经被保留(除非我搞错了?) - Adi

-2

尝试将 MediaPlayer.framework 添加到您的项目中


MediaPlayer.frameworkAVAudioPlayer位于AVFoundation.framework中,不应该需要MediaPlayer。能否详细说明一下? - Ivan Vučica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接