我在 iPhone 4S 上运行 Instruments。 我在这个方法中使用 AVAudioPlayer:
-(void)playSound{
NSURL *url = [self.word soundURL];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
if (!error) {
[audioPlayer prepareToPlay];
[audioPlayer play];
}else{
NSLog(@"Problem With audioPlayer on general card. error : %@ | url %@",[error description],[url absoluteString]);
}
播放声音文件时出现泄漏:
泄漏的对象:
1.
对象:NSURL
负责图书馆:基金会
负责框架:基础 -[NSURL(NSURL) allocWithZone:]
2.
对象:_NSCFString
负责图书馆:基金会
负责的框架:基金会-[NSURL(NSURL) initFileURLWithPath:]
Instruments 没有直接指向我的代码,所以我很难找到泄漏原因。
我的问题
什么会导致泄漏? 或当我不对代码负责时,如何定位漏洞?
编辑 这是 Instruments cycles View 中的架构: 谢谢沙尼
最佳答案
看起来是 Apple 代码中的漏洞...我尝试同时使用这两种
-[AVAudioPlayer initWithData:error:]
和-[AVAudioPlayer initWithContentsOfURL:error:]
在第一种情况下,分配的AVAudioPlayer
实例保留了传入的NSData
。第二种,保留传入的NSURL
:
我附上了 Instruments 窗口的一些屏幕截图,其中显示了传入的 NSData
对象的保留/释放历史记录。
你可以看到AVAudioPlayer
对象然后创建了一个C++对象AVAudioPlayerCpp
,它再次保留了NSData:
稍后,当 AVAudioPlayer
对象被释放时,NSData
也被释放,但是关联的 AVAudioPlayerCpp
从来没有释放调用。 .(你可以从附图中看出)
如果你想避免泄露 NSData/NSURL,你似乎必须使用不同的解决方案来播放媒体..
这是我的测试代码:
-(void)timerFired:(NSTimer*)timer
{
NSString * path = [[ NSBundle mainBundle ] pathForResource:@"song" ofType:@"mp3" ] ;
NSError * error = nil ;
NSData * data = [ NSData dataWithContentsOfFile:path options:NSDataReadingMapped error:&error ] ;
if ( !data )
{
if ( error ) { @throw error ; }
}
AVAudioPlayer * audioPlayer = data ? [[AVAudioPlayer alloc] initWithData:data error:&error ] : nil ;
if ( !audioPlayer )
{
if ( error ) { @throw error ; }
}
if ( audioPlayer )
{
[audioPlayer play];
[ NSThread sleepForTimeInterval:0.75 ] ;
[ audioPlayer stop ] ;
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// ...
[ NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector( timerFired: ) userInfo:nil repeats:YES ] ;
// ...
return YES;
}
关于ios - 使用 ARC 从 NSURL 和 AVAudioPlayer 泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12498015/