2009-08-29 51 views
6

我被困在与AVAudioPlayer相关的一些奇怪的内存泄漏问题上,在尝试了所有想到的东西之后,我需要帮助。AVAudioPlayer内存泄漏

下面是问题的简短描述 - 代码出现后。 我初始化了我的播放器并开始在无限循环中播放音轨(无限循环或一次播放并未改变问题)。 音乐开始几秒钟后,我切换到另一首音轨,因此我创建了一个新的播放器,初始化它,释放旧的(正在播放的),然后设置新的播放器并播放它。在那个时间点(在我称为新玩家 - [玩家玩]之后),我得到一个内存泄漏(3.5Kb)。

我试过如下:

  • 停止老玩家,然后释放它 - 没有影响

  • 版本播放器的播放指令后,正确的 - 没有开始踢

  • 释放两次旧玩家 - 崩溃

  • 内存泄漏当我创建并播放内容时不会发生第一个玩家!

此外,在参考它说,“玩”是异步,因此它很可能通过增加1引用计数,但是在这种情况下,为什么没有[播放器停止]帮助?

感谢,

下面是我如何使用它的代码的某些部分:

- (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; 

}

回答

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方法,它可能更容易追查。

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

+0

感谢您的回答。 是的 - 我确认它是带有乐器的AVAudioPlayer。 至于方法 - 我使用这一个,因为我实际上保存了不同的曲目,并通过匹配名称并且如果它们没有播放(而不是几次下载相同的曲目)来重复使用它们。 因为我知道我做了一个'Alloc'后,从调用者得到玩家,我知道它已被保留(除非我错了?) – Adi 2009-08-31 07:21:31

7

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

我已经在我的应用程序中证实,这删除了我的AVAudioPlayer泄漏100%。

- (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; 
} 
+1

我认为应该键入NSData * audioData在第二个行... – SpaceDog 2010-08-07 19:30:02

+0

这段代码真的很奇怪,没有理由将alloc和init调用分开。为更好的一般方法,请参阅http://stackoverflow.com/questions/17603551/arc-forbids-autorelease/17604365#17604365或者你可以添加autorelease像[[[AVAudioPlayer分配] initWithData:audioData错误:NULL] autorelease ] – MoDJ 2013-07-15 22:08:52

-2

尝试增加MediaPlayer.framework到项目

+0

'MediaPlayer.framework'? 'AVAudioPlayer'位于'AVFoundation.framework'中,不需要'MediaPlayer'。谨慎阐述? – 2011-05-23 13:23:34

2

实现协议AVAudioPlayerDelegate及其方法audioPlayerDidFinishPlaying:成功:再松开音频播放器对象

如。

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