Okay, this should be an easy one for the pros out there (disclaimer, I’m sort of a noob in Obj-C, mainly I use in C#). I have a UIViewController subclass; one of its properties is an AVAudioPlayer object. When I write this code:
NSString *path = [[NSBundle mainBundle] pathForResource:@"example" ofType:@"caf"];
NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
[player initWithContentsOfURL:url error:NULL];
[url release];
[player setDelegate:self];
[player prepareToPlay];
[player play];
Nothing happens.
When I do this, which is clearly the correct way of doing it:
NSString *path = [[NSBundle mainBundle] pathForResource:@"example" ofType:@"caf"];
NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *ap = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:NULL];
self.player = ap;
[ap release];
[url release];
[player setDelegate:self];
[player prepareToPlay];
[player play];
…everything works beautifully.
Why do I need to allocate an object and then set my property equal to that? Apologies if this is a way-too-common question.
This is because in your first example you are not creating the AVAudioPlayer with alloc. This means you don’t actually have a valid AVAudioPlayer in memory.
And also you are not using taking the return value of init*. Since init often works on the instance itself, this would probably work in many cases if you had done the alloc and assigned it to player, but you can’t rely on this, and its the convention to use the return value with a
Class *var = [[Class alloc] init]form.If you wanted shorter working code, you could replace
with