如何正确发布音频? [AVAudioPlayer]

时间:2011-01-09 21:24:03

标签: iphone objective-c memory-management avaudioplayer

我的iOS应用程序^^需要帮助。我想知道我是否正确发布AVAudioPlayer

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

2 个答案:

答案 0 :(得分:3)

我认为您实施解决方案的方式可能更好,并了解为什么会帮助您学习。

首先,在Objective-C(至少是Cocoa和Cocoa Touch)中使用以小写字母开头的变量和方法名称。例如,您的“媒体”变量应为“媒体”,而“PlaySound”方法应为“playSound”。

其次,您的“media”变量被声明为全局变量,最好将其声明为MyViewController.h文件中@interface中的实例变量。因此,MyViewController的每个实例都有一个名为“media”的实例变量,它更适合面向对象的封装概念。就个人而言,我会把变量称为“玩家”,因为我觉得这个变量更好(我从这里开始使用“玩家”)。

第三,如果你的“playSound”总是发出与你相同的声音,那么最好将“media”对象的分配移动到“init ...”方法(例如,initWithNibName) :bundle:方法)。这样你只需要实例化一次对象而不是每次调用你的“playSound”方法(我认为它可以被多次调用)。你是“playSound”方法只需要调用[player play]。这样就没有理由将你的路径作为实例变量。

最后,如果您按上述方式执行操作,则在dealloc方法中调用[player release]是有意义的。当释放类的实例并释放属于它的“播放器”实例时,将调用dealloc方法。

以下是我的更改内容。

<强> 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

答案 1 :(得分:0)

在Cocoa中思考记忆的最好方法是,“我有没有发布我拥有的东西?”。在您给出的示例中,您通过分配其内存来创建“Media”变量的所有权,因此在您的类和该分配之间创建一个合同,以便在您完成对象时释放您对该对象的所有权。

换句话说,当你创建那个对象时,它的保留计数为1,这意味着你是它的拥有者,并且一旦完成它就需要放弃它的所有权。这可能不一定意味着该对象将立即解除分配; Cocoa内存范例意味着如果你收到一个你没有创建的对象,但需要它“保持活力”足够的时间让你使用它,你可以调用'retain',然后'release'当你是完成它。

在上面的附录中,是'autorelease'的概念; pathForResource:方法在返回时将对象的所有权传递给你 - 换句话说,在创建对象之后,它通过在返回对象之前调用'autorelease'来放弃所有权本身,因此强迫你的类负责决定如何处理它(你可以'保留'它,然后在某个地方稍后要求'释放',或者只是在它被解除分配之前使用它。)

我建议阅读Apple的内存指南;一旦你掌握了你将要设定的概念: Memory Management Programming Guide