How to release audio properly? [AVAudioPlayer]
I need help with my iOS
application ^^,. I want to know if I'm releasing AVAudioPlayer
开发者_运维技巧 correctly.
MyViewController.h
#import <UIKit/UIKit.h>
@interface MyViewController : UIViewController
{
NSString *Path;
}
- (IBAction)Playsound;
@end
MyViewController.m
#import <AVFoundation/AVAudioPlayer.h>
#import "MyViewController.h"
@implementation MyViewController
AVAudioPlayer *Media;
- (IBAction)Playsound
{
Path = [[NSBundle mainBundle] pathForResource:@"Sound" ofType:@"wav"];
Media = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:Path] error:NULL];
[Media play];
}
- (void)dealloc
{
[Media release];
[super viewDidUnload];
}
@end
I think that the way you've implemented your solution could be better and understanding why will help you learn.
First, it's convention in Objective-C (at least Cocoa and Cocoa Touch) to name variables and method names starting with a lowercase letter. For example, your "Media" variable should be "media" and your "PlaySound" method should be "playSound".
Second, your "media" variable is declared as a global variable and it would be better to declare it as an instance variable in the @interface
in your MyViewController.h file. Thus, each instance of MyViewController
would have an instance variable called "media" which better fits the object-oriented concept of encapsulation. Personally, I would call the variable "player" because it seems to me to describe what the variable is better (I'll use "player" from here on out).
Third, if your "playSound" is always going to play the same sound as you have it, it may be better to move your allocation of the "media" object to the "init..." method (e.g., initWithNibName:bundle: method). This way you instantiate the object only once and not each time your "playSound" method is called (I presume that it can be called multiple times). You're "playSound" method would only need to call [player play]
. This way there's really no reason to have your path as an instance variable.
Last, if you do things as above then calling [player release] in the dealloc method makes sense. The dealloc method is called when an instance of the class is deallocated and that deallocates the instance of "player" that belongs to it.
Here's what my changes would look like.
MyViewController.h
#import <UIKit/UIKit.h>
@class AVAudioPlayer;
@interface MyViewController : UIViewController
{
AVAudioPlayer *player;
}
- (IBAction)playSound;
@end
MyViewController.m
#import <AVFoundation/AVAudioPlayer.h>
#import "MyViewController.h"
@implementation MyViewController
- (id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)nibBundleOrNil
{
if (self = [super initWithNibName:nibName bundle:nibBundleOrNil]) {
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Sound" ofType:@"wav"];
player = [AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:filePath] error:NULL];
}
return self;
}
- (IBAction)playSound
{
[player play];
}
- (void)dealloc
{
[player release];
[super dealloc];
}
@end
The best way to think of memory in Cocoa is, 'have I released anything I own?'. In the example you've given, you create ownership of the 'Media' variable by allocating its memory, therefore creating a contract between your class and that allocation to release your ownership of the object when you're done with it.
In other words, when you created that object, it had a retain count of 1, implying that you are the owner of it, and need to relinquish ownership of it once finished with it. That may not necessarily mean that the object will be deallocated immediately; the Cocoa memory paradigm means that if you ever receive an object you didn't create, yet need it to 'stay alive' enough time for you to work with it, you call 'retain', and then 'release' when you're finished with it.
In addendum to the above, is the concept of 'autorelease'; the pathForResource:
method passes ownership of the object to you when it returns - in other words, after creating the object it relinquishes ownership itself by calling 'autorelease' on the object before returning it, therefore forcing upon your class the responsibility of deciding what to do with it (you could 'retain' it, then requiring a 'release' somewhere later, or simply use it until it is deallocated).
I'd recommend reading Apple's Guide on memory; once you've mastered the concepts you'll be set: Memory Management Programming Guide
精彩评论