Прежде всего, старайтесь избегать таких утверждений:
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"]];