使用ARC从NSURL和AVAudioPlayer泄漏

sha*_*oga 20 memory-leaks nsurl instruments ios

我是iPhone 4S上的runung 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]);
}
Run Code Online (Sandbox Code Playgroud)

我在播放声音文件时遇到泄漏:

泄漏的物体:

1.

对象:NSURL

负责任的图书馆:基金会

负责框架:基金会 - [NSURL(NSURL)allocWithZone:]

2.

对象:_NSCFString

负责任的图书馆:基金会

负责框架:基础 - [NSURL(NSURL)initFileURLWithPath:]

仪器没有直接指向我的代码,因此我发现很难找到泄漏原因.

我的问题

什么可能导致泄漏? 或者当我对代码不负责时,如何定位泄漏?

编辑 这是仪器周期视图中的模式: 在此输入图像描述 谢谢Shani

nie*_*bot 19

看起来是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;
}
Run Code Online (Sandbox Code Playgroud)