【问题标题】:AVAudioPlayer memory leakAVAudioPlayer 内存泄漏
【发布时间】:2010-11-24 01:36:47
【问题描述】:

我遇到了一些与 AVAudioPlayer 相关的奇怪内存泄漏问题,在尝试了所有想到的事情后我需要帮助。

这是问题的简短描述 - 代码紧随其后。 我初始化我的播放器并开始无限循环播放音轨(无限循环或一次播放并没有改变问题)。 音乐开始几秒钟后,我切换到另一个音轨,因此我创建了一个新播放器,对其进行初始化,释放旧播放器(正在播放),然后将新播放器放置到位并播放。

在那个时间点(就在我调用新播放器后 - [播放器播放])我遇到了内存泄漏(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;

}

【问题讨论】:

    标签: xcode memory avaudioplayer memory-leaks


    【解决方案1】:

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

    例如。

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

    【讨论】:

      【解决方案2】:

      这是创建 AVAudioPlayer 而不会导致内存泄漏的方法。 See this page for explaination

      我已在我的应用中确认,这会 100% 消除我的 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;
      }
      

      【讨论】:

      【解决方案3】:

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

      【讨论】:

      • MediaPlayer.framework? AVAudioPlayer 位于 AVFoundation.framework 中,不应需要 MediaPlayer。需要详细说明吗?
      【解决方案4】:

      就我所见,您的代码在我看来还不错,所以可能是其他地方的代码导致了问题。

      我会说你在使用一种奇怪的习语。我不会在片场保留创建和发布,而是这样做:

          // 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 方法时,这可能更容易追踪。

      另外,验证它实际上是一个正在泄漏的 AVAudioPlayer 对象。仪器应该能够为您验证这一点。

      【讨论】:

      • 感谢您的回答。是的 - 我确认它是带有 Instruments 的 AVAudioPlayer。至于方法 - 我使用这个是因为我实际上保存了不同的曲目并通过匹配名称以及如果它们没有播放(而不是多次下载相同的曲目)来重用它们。因为我知道我在对其执行“分配”后从调用者那里获得了 Player,所以我知道它已经被保留(除非我弄错了?)
      猜你喜欢
      • 1970-01-01
      • 2011-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多