0

这可能是一个基本问题,但我对 Cocoa、Objective-C 和 OOP 很陌生,而且我无法在任何地方找到答案。

在我正在编写的应用程序中,我想在用户按下特定按钮时播放声音文件。我为此使用了 NSSound,并且在实现它时没有问题。问题是,我只知道如何通过每次按下按钮时创建一个新的 NSSound 对象来做到这一点:

- (IBAction)playSound:(id)sender {
    NSSound *sound = [[NSSound alloc] initWithContentsOfFile:kSoundFilePath byReference:YES];
    [sound play];
}

这对我来说是个问题,因为如果用户在文件完成播放之前反复单击按钮,它将创建 NSSound 的新实例,并且它们都将相互叠加播放,这是我不想要的。有没有一种方法可以在该方法之外创建 NSSound 对象,并让按钮的 IBAction 方法检查 NSSound 是否正在播放,然后再告诉它再次播放?

4

2 回答 2

1

是的先生。这可以通过多种方式完成。一种简单的方法是使用私有属性:

/* these are in the SAME FILE */
@interface MyClass ()

    @property (nonatomic, retain) NSSound *sound;

@end

@implementation MyClass

    - (IBAction)playSound:(id)sender {
        self.sound = [[NSSound alloc] initWithContentsOfFile:kSoundFilePath byReference:YES];
        [self.sound play];
    }

@end

你也可以这样做。编辑:正如 Avt 在评论中所说,以他的方式使用全局变量时存在一些问题。如果您要创建此类的多个实例,则最好使用例设计模式。为了解释,这里有一篇由可敬的 Mattt Thompson 撰写的文章

@implementation MyClass

    NSSound *sound;

    ...

    - (IBAction)playSound:(id)sender {
        sound = [[NSSound alloc] initWithContentsOfFile:kSoundFilePath byReference:YES];
        [sound play];
    }

@end

我个人使用第一种方式,因为从编程的角度来看,它更清楚地表明您的类拥有创建的对象。虽然第二种方式是合法的,但对象所属的位置不太清楚......它可能是方法范围内的局部变量,或者其他东西。我强烈推荐第一种方式,但为了教育的利益,您应该了解所有可能的方式。

于 2014-02-18T23:55:42.660 回答
0

在你的类的声明中,它应该看起来像这样:

@implementation MyViewController

添加这个:

@implementation MyViewController {
  NSSound* sound;
}

然后在 viewDidLoad 中:

sound = [[NSSound alloc] initWithContentsOfFile:kSoundFilePath byReference:YES];

最后:

- (IBAction)playSound:(id)sender {
    [sound play];
}
于 2014-02-18T23:57:53.177 回答