尝试使用AVAudioPlayer修复内存泄漏

时间:2010-01-23 20:40:59

标签: iphone objective-c

为了修复内存泄漏,我试图在我的.m文件中实现此代码:

AVAudioPlayer *audioPlayer;

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

然后尝试通过以下方式调用它:

[audioPlayer audioPlayerWithContentsOfFile: [NSString stringWithFormat:@"%@/knock_knock.wav", [[NSBundle mainBundle] resourcePath]]];

头文件包含:

- (AVAudioPlayer *) audioPlayerWithContentsOfFile: (NSString *) path;

编译一个警告: AVAudioPlayer可能无法响应'-audioPlayerWithContentsOfFile:' (没有匹配签名的消息将被假定为返回'id'并接受'...'作为争论。

每次我得到这种语言的东西,我遇到这样的东西,我花了几个小时试图弄明白。有人能帮忙吗?一如既往,提前谢谢。

...地理位置

2 个答案:

答案 0 :(得分:3)

首先,尽量避免这样的陈述:

AVAudioPlayer *player = [AVAudioPlayer alloc];

因为你留下了一个未初始化的对象,你可能碰巧忘记稍后启动它。在正常情况下,您应该始终将-init ...方法发送到新分配的对象。换句话说,正确的方法是在一个“句子”中调用+ alloc和-init。

其次,如果AVAudioPlayer的-initWithData:error:返回nil,则无法释放它,因为您将-autorelease消息发送到nil。按照惯例,如果一个对象不能被引入,它应该释放自己并返回nil。这就是AVAudioPlayer无法读取或识别音频数据时所做的事情。换句话说,不要试图自己释放它。

因此,您方法的简化版本如下:

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

确保将消息发送到正确的类,因为AVAudioPlayer未实现您的-audioPlayerWithContentsOfFile:方法。看看它的定义和实现在哪里。

@interface SomeClass : NSObject
...
- (AVAudioPlayer *)audioPlayerWithContentsOfFile:(NSString *) path;
@end

上面定义了-audioPlayerWithContentsOfFile:对于SomeClass类的实例,所以你应该将消息发送到SomeClass的实例,而不是AVAudioPlayer。如果您想为AVAudioPlayer类定义此方法,请改为:

@interface AVAudioPlayer (MyExtensions)
+ (AVAudioPlayer *)audioPlayerWithContentsOfFile:(NSString *) path;
@end

@implementation AVAudioPlayer (MyExtensions)
+ (AVAudioPlayer *)audioPlayerWithContentsOfFile:(NSString *) path {
        NSData *audioData = [NSData dataWithContentsOfFile: path];
        return [[[AVAudioPlayer alloc] initWithData:audioData error: NULL] autorelease];
}
@end

使用它:

[AVAudioPlayer audioPlayerWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"knock_knock" ofType:@"wav"]];

答案 1 :(得分:0)

  • 不要像这样构成路径。使用NSBundle的pathForResource:ofType:或类似的。

  • 不要从+alloc(或任何其他指定的初始值设定项)中拆分-init。这是一个样式问题,标准为[[AVAudioPlayer alloc] initWithData: foo error: &bar]

  • 处理错误并在出现问题时将其打印出来。它通常会提供线索。

现在,你的实际错误。

  

AVAudioPlayer可能无法响应   '-audioPlayerWithContentsOfFile:'

这表示您正在尝试将方法调用发送到AVAudioPlayer类的实例。这是有意的吗?即你的.m文件是类AVAudioPlayer的实现吗?

您的代码看起来有点时髦。你有一个名为audioPlayer的实例变量,但我没有看到任何指定它的东西。

此外,请确保将包含方法声明的头文件导入到.m中。并确保您正在发送实例,而不是类。