Попытка исправить утечку памяти с помощью AVAudioPlayer - PullRequest
0 голосов
/ 23 января 2010

В попытке исправить утечку памяти я пытаюсь реализовать этот код в моем файле .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 и принимают «...» в качестве аргументов.

Каждый раз, когда я получаю этот язык, я сталкиваюсь с такими вещами, которые я часами пытаюсь выяснить. Кто-нибудь может помочь? Как всегда, заранее спасибо.

Geo ...

Ответы [ 2 ]

3 голосов
/ 24 января 2010

Прежде всего, старайтесь избегать таких утверждений:

AVAudioPlayer *player = [AVAudioPlayer alloc];

потому что у вас остался неинициализированный объект, и вы можете просто забыть инициировать его позже. В обычных обстоятельствах вы должны всегда отправлять -init ... метод недавно выделенному объекту. Другими словами, правильным способом является вызов + alloc и -init в одном «предложении».

Во-вторых, если AVAudioPlayer's -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"]];
0 голосов
/ 24 января 2010
  • Не сочиняйте такие пути. Используйте NSBundle pathForResource:ofType: или аналогичный.

  • Не разделять +alloc от -init (или любого другого назначенного инициализатора). Это проблема стиля, и стандартом будет [[AVAudioPlayer alloc] initWithData: foo error: &bar].

  • Обработайте ошибку и распечатайте ее, если что-то идет не так. Обычно он предлагает подсказки.

Теперь перейдем к вашей фактической ошибке.

AVAudioPlayer может не отвечать на '-AudioPlayerWithContentsOfFile:'

Это означает, что вы пытаетесь отправить вызов метода в экземпляр класса AVAudioPlayer. Это предназначено? То есть ваш файл .m является реализацией класса AVAudioPlayer?

Ваш код выглядит немного прикольным. У вас есть переменная экземпляра с именем audioPlayer, но я нигде не вижу ничего, что ей назначается.

Также убедитесь, что файл заголовка, содержащий объявление метода, импортирован в ваш .m. И убедитесь, что вы отправляете сообщения экземпляру, а не классу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...