2

你好 StackOverflow 大师。这是我在这里的第一个问题,所以我很高兴能直接加入。

我试图更好地理解 iOS 数组,但我遇到了障碍。我正在制作一个使用 FMOD 的声音应用程序。我的一切工作正常,但我有 9 个按钮,它们的功能几乎完全相同,只是每个按钮在按下时播放不同的 .wav 文件,然后在释放时停止声音。我想将它放入一个数组中并简化和缩短我的代码,这就是我迷路的地方。我剥离了代码以显示我目前正在做的事情。有任何想法吗?

。H

@interface {

FMOD::Sound    *sound1;
FMOD::Sound    *sound2;
FMOD::Sound    *sound3;
FMOD::Sound    *sound4;
FMOD::Sound    *sound5;
FMOD::Sound    *sound6;
FMOD::Sound    *sound7;
FMOD::Sound    *sound8;
FMOD::Sound    *sound9;

}

- (IBAction)playSound1:(id)sender;
- (IBAction)stopSound1:(id)sender;
- (IBAction)playSound2:(id)sender;
- (IBAction)stopSound2:(id)sender;
- (IBAction)playSound3:(id)sender;
- (IBAction)stopSound3:(id)sender;
- (IBAction)playSound4:(id)sender;
- (IBAction)stopSound4:(id)sender;
- (IBAction)playSound5:(id)sender;
- (IBAction)stopSound5:(id)sender;
- (IBAction)playSound6:(id)sender;
- (IBAction)stopSound6:(id)sender;
- (IBAction)playSound7:(id)sender;
- (IBAction)stopSound7:(id)sender;
- (IBAction)playSound8:(id)sender;
- (IBAction)stopSound8:(id)sender;
- (IBAction)playSound9:(id)sender;
- (IBAction)stopSound9:(id)sender;

米。

- (void)viewWillAppear:(BOOL)animated {

[[NSString stringWithFormat:@"%@/sound1.wav", [[NSBundle mainBundle] resourcePath]] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];
    result = system->createSound(buffer, FMOD_SOFTWARE | FMOD_LOOP_NORMAL, NULL, &sound1);
    ERRCHECK(result);


    [[NSString stringWithFormat:@"%@/sound2.wav", [[NSBundle mainBundle] resourcePath]] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];
    result = system->createSound(buffer, FMOD_SOFTWARE | FMOD_LOOP_NORMAL, NULL, &sound2);
    ERRCHECK(result);


    [[NSString stringWithFormat:@"%@/sound3.wav", [[NSBundle mainBundle] resourcePath]] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];
    result = system->createSound(buffer, FMOD_SOFTWARE | FMOD_LOOP_NORMAL, NULL, &sound3);
    ERRCHECK(result);


    [[NSString stringWithFormat:@"%@/sound4.wav", [[NSBundle mainBundle] resourcePath]] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];
    result = system->createSound(buffer, FMOD_SOFTWARE, NULL, &sound4);
    ERRCHECK(result);
    result = sound4->setMode(FMOD_LOOP_NORMAL);
    ERRCHECK(result);

    [[NSString stringWithFormat:@"%@/sound5.wav", [[NSBundle mainBundle] resourcePath]] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];
    result = system->createSound(buffer, FMOD_SOFTWARE | FMOD_LOOP_NORMAL, NULL, &sound5);
    ERRCHECK(result);


    [[NSString stringWithFormat:@"%@/sound6.wav", [[NSBundle mainBundle] resourcePath]] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];
    result = system->createSound(buffer, FMOD_SOFTWARE | FMOD_LOOP_NORMAL, NULL, &sound6);
    ERRCHECK(result);


    [[NSString stringWithFormat:@"%@/sound7.wav", [[NSBundle mainBundle] resourcePath]] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];
    result = system->createSound(buffer, FMOD_SOFTWARE | FMOD_LOOP_NORMAL, NULL, &sound7);
    ERRCHECK(result);


    [[NSString stringWithFormat:@"%@/sound8.wav", [[NSBundle mainBundle] resourcePath]] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];
    result = system->createSound(buffer, FMOD_SOFTWARE | FMOD_LOOP_NORMAL, NULL, &sound8);
    ERRCHECK(result);


    [[NSString stringWithFormat:@"%@/sound9.wav", [[NSBundle mainBundle] resourcePath]] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];
    result = system->createSound(buffer, FMOD_SOFTWARE | FMOD_LOOP_NORMAL, NULL, &sound9);
    ERRCHECK(result);

}



- (IBAction)playSound1:(id)sender
{
    FMOD_RESULT result = FMOD_OK;
    result = system->playSound(FMOD_CHANNEL_FREE, sound1, false, &wob01);
    ERRCHECK(result);    
}

- (IBAction)stopSound1:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = wob01->stop();
    ERRCHECK(result);   
}

- (IBAction)playSound2:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = system->playSound(FMOD_CHANNEL_FREE, sound2, false, &wob02);
    ERRCHECK(result);    
}

- (IBAction)stopSound2:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = wob02->stop();
    ERRCHECK(result);   
}

- (IBAction)playSound3:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = system->playSound(FMOD_CHANNEL_FREE, sound3, false, &wob03);
    ERRCHECK(result);    
}

- (IBAction)stopSound3:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = wob03->stop();
    ERRCHECK(result);   
}

- (IBAction)playSound4:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = system->playSound(FMOD_CHANNEL_FREE, sound4, false, &wob04);
    ERRCHECK(result);    
}

- (IBAction)stopSound4:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = wob04->stop();
    ERRCHECK(result);   
}

- (IBAction)playSound5:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = system->playSound(FMOD_CHANNEL_FREE, sound5, false, &wob05);
    ERRCHECK(result);    
}

- (IBAction)stopSound5:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = wob05->stop();
    ERRCHECK(result);   
}

- (IBAction)playSound6:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = system->playSound(FMOD_CHANNEL_FREE, sound6, false, &wob06);
    ERRCHECK(result);    
}

- (IBAction)stopSound6:(id)sender
{
    FMOD_RESULT result = FMOD_OK;

    result = wob06->stop();
    ERRCHECK(result);   
}

- (IBAction)playSound7:(id)sender
{
    FMOD_RESULT result = FMOD_OK;
    result = system->playSound(FMOD_CHANNEL_FREE, sound7, false, &wob07);
    ERRCHECK(result);    
}

- (IBAction)stopSound7:(id)sender
{
    FMOD_RESULT result = FMOD_OK;
    result = wob07->stop();
    ERRCHECK(result);   
}

- (IBAction)playSound8:(id)sender
{
    FMOD_RESULT result = FMOD_OK;
    result = system->playSound(FMOD_CHANNEL_FREE, sound8, false, &wob08);
    ERRCHECK(result);    
}

- (IBAction)stopSound8:(id)sender
{
    FMOD_RESULT result = FMOD_OK;
    result = wob08->stop();
    ERRCHECK(result);   
}

- (IBAction)playSound9:(id)sender
{
    FMOD_RESULT result = FMOD_OK;
    result = system->playSound(FMOD_CHANNEL_FREE, sound9, false, &wob09);
    ERRCHECK(result);    
}

- (IBAction)stopSound9:(id)sender
{
    FMOD_RESULT result = FMOD_OK;
    result = wob09->stop();
    ERRCHECK(result);   
}

如您所见,所有代码都是重复的。这是我能够让它工作的唯一方法,但我知道这些可以放入一个数组中,我就是想不通。可能是一个 NSMutableArray 并列出“sound1”、“sound2”等。然后在界面生成器中为每个按钮分配一个标签?理想情况下,我想要一个用于 stopSound 的函数,一个用于 playSound 等,它使用标签来播放或停止正确的声音文件。使用 FMOD 的 system->createSound() 时,最后一个参数是一个变量,用于存储新创建的声音。有没有办法将其存储在数组或字典中?如果是这样,我无法弄清楚。

任何建议都将不胜感激。我很想不要再为这个简单的问题头疼了。

谢谢!

4

3 回答 3

8

我会将声音包装成一个子类NSObject并使其成为一个独立的单元。一个声音会有像play, stop, pause, 和像isPlaying, 这样的访问器这样的操作。

然后为了使其更加通用,我将搜索与该模式匹配的所有文件"*.wav",然后为每个匹配的文件名,Sound使用该文件名初始化一个对象,并将其添加到数组中。

这是我想象的 Sound 对象的样子:

@interface Sound : NSObject

@property FMOD::Sound *sound;

- (id)initWithSoundFilePath:(NSString *)path;
- (void)play;
- (void)stop;

@end

@implementation Sound

- (void)dealloc {
    // free the memory occupied by the sound pointer here
}

- (id)initWithSoundFilePath:(NSString *)path {
    self = [super init];
    if (self) {
        result = system->createSound(path, FMOD_SOFTWARE | FMOD_LOOP_NORMAL, NULL, &sound);
        ERRCHECK(result);
    }
    return self;
}

- (void)play {
    FMOD_RESULT result = FMOD_OK;
    result = system->playSound(FMOD_CHANNEL_FREE, sound, false, /* What is this wob? */);
    ERRCHECK(result);
}

- (void)stop {
    FMOD_RESULT result = FMOD_OK;
    result = /* What is this wob */->stop();
    ERRCHECK(result);   
}

@end

所以你有它。声音现在被很好地封装了。我发现这个答案有助于查找某个目录中符合某些条件的所有文件的列表。您可以在视图控制器中使用它来自动生成所有相关的 Sound 对象并将其添加到数组中。

- (NSArray *)getPathsOfSoundFiles {
    NSString *rootPath = [[NSBundle mainBundle] resourcePath];
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray *files = [fm contentsOfDirectoryAtPath:rootPath error:nil];
    NSPredicate *soundFileFilter = [NSPredicate predicateWithFormat:@"self ENDSWITH '.wav'"];
    NSArray *soundFilePaths = [files filteredArrayUsingPredicate:soundFileFilter];
    return soundFilePaths;
}

好的,现在您可以检索所有 .wav 文件的路径,下一步是在您的viewWillAppear或任何最有意义的方法中初始化它们。

- (void)viewWillAppear:(BOOL)animated {
    NSArray *paths = [self getPathsOfSoundFiles];
    NSMutableArray *sounds = [NSMutableArray array];
    for (NSString *path in paths) {
        Sound *sound = [[Sound alloc] initWithSoundFilePath:path];
        [sounds addObject:sound];
    }
    self.sounds = sounds;
}

并且通过声音阵列设置,播放和停止给定的声音变得相当容易。使用可以创建一个将索引放入数组的方法,或者可能是一个Sound对象本身并完成这项工作。

- (void)playSoundAtIndex:(NSUInteger)soundIndex {
    Sound *sound = [self.sounds objectAtIndex:soundIndex];
    [sound play];
}

- (void)stopSoundAtIndex:(NSUInteger)soundIndex {
    Sound *sound = [self.sounds objectAtIndex:soundIndex];
    [sound stop];
}
于 2012-09-08T21:41:33.107 回答
1

您可以大量概括您的代码:

  • 使用数组来存储你的声音和“wobs”
  • 使用类似的循环[NSString stringWithFormat:@"%@/sound%i.wav", [[NSBundle mainBundle] resourcePath], index]
  • 只有-playSound:一个-stopStound:操作使用sender'标签(您可以在 Interface Builder 中设置或在视图控制器的代码中创建按钮时自动化)来确定要播放的声音或停止的 wob。
于 2012-09-08T21:43:45.693 回答
-3

我强烈建议您继承 UIButton 并覆盖触摸方法以在发生这些操作时播放音频文件。当您子类化 UIButton 时,您需要在头文件中设置一个属性,以便您可以传入音频文件或音频文件所在位置的字符串,这样就可以轻松地将其动态化。

然后在主文件中,就像我说的那样,只需覆盖那些触摸方法(touchesBegan、touchesEnded 等)来播放您可以传入我们在头文件中定义的自定义属性。

这就是我至少要解决您的问题的方式,然后您只有一个 UIButton 子类可以根据您传入的音频文件执行完全相同的操作。

于 2012-09-08T20:34:27.593 回答