9

我尝试扩展 cocos2d 的 SimpleAudioEngine 的功能,使其能够像某种链条一样依次播放多个音效。我试图通过扩展来做到这一点。但是我现在意识到我可能还需要一个 iVar 来记住所有声音文件的名称,并需要一个 iVar 来记住当前正在播放的声音。

但是,我似乎无法在类别中添加 iVar。相反,我尝试使用扩展名,但似乎它们需要在类的原始 .m 文件中,这样也不起作用。还有另一种方法可以让我这样做吗?

带有类别的标题

#import <Foundation/Foundation.h>
@interface SimpleAudioEngine(SoundChainHelper)<CDLongAudioSourceDelegate>
-(void)playSoundChainWithFileNames:(NSString*) filename, ...;
@end

以及带有扩展名的 .m 文件:

#import "SoundChainHelper.h"

@interface SimpleAudioEngine() {
    NSMutableArray* soundsInChain;
    int currentSound;
}
@end

@implementation SimpleAudioEngine(SoundChainHelper)

// read in all filenames and start off playing process
-(void)playSoundChainWithFileNames:(NSString*) filename, ... {
    soundsInChain = [[NSMutableArray alloc] initWithCapacity:5];

    va_list params;
    va_start(params,filename);

    while (filename) {
        [soundsInChain addObject:filename];
        filename = va_arg(params, NSString*);
    }
    va_end(params);
    currentSound = 0;
    [self cdAudioSourceDidFinishPlaying:nil];
}

// play first file, this will also always automatically be called as soon as the previous sound has finished playing
-(void)cdAudioSourceDidFinishPlaying:(CDLongAudioSource *)audioSource {
    if ([soundsInChain count] > currentSound) {
        CDLongAudioSource* mySound = [[CDAudioManager sharedManager] audioSourceForChannel:kASC_Right];
        [mySound load:[soundsInChain objectAtIndex:0]];
        mySound.delegate = self;
        [mySound play];
        currentSound++;
    }
}

@end

或者,我尝试将 iVar 定义为将编译的属性。但是,我既不能合成它们,也没有任何其他可能将它们绑定到任何方法。

我尝试将功能实现为 SimpleAudioEngine 的一个类别,这样我只需要记住一个处理我所有声音问题的类。这样我就可以像这样简单地创建一个链:

[[SimpleAudioEngine sharedEngine] playSoundChainWithFileNames:@"6a_loose1D.mp3", @"6a_loose2D.mp3", @"6a_loose3D.mp3", @"6a_loose4D.mp3", @"6b_won1D.mp3", nil];

如果有另一种产生相同/相似结果的方法,我也将非常感激。

4

2 回答 2

24

您不能将实例变量(或合成的@properties)添加到类别是正确的。您可以使用 Objective-C 运行时对关联引用的支持来解决此限制

像这样的东西:

在您的 .h 中:

@interface SimpleAudioEngine (SoundChainHelper)
    @property (nonatomic, retain) NSMutableArray *soundsInChain;
@end

在您的 .m 中:

#import <objc/runtime.h>
static char soundsInChainKey;

@implementation SimpleAudioEngine (SoundChainHelper)

- (NSMutableArray *)soundsInChain
{
   return objc_getAssociatedObject(self, &soundsInChainKey);
}

- (void)setSoundsInChain:(NSMutableArray *)array
{
    objc_setAssociatedObject(self, &soundsInChainKey, array, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

(标准免责声明适用。我在浏览器中输入了这个,并没有测试它,但我以前使用过这种技术。)

我链接到的文档有更多关于关联引用如何工作的信息。

于 2012-05-08T16:37:07.787 回答
-1

您不能添加 iVar,但可以添加属性变量。如下所示:

在您的 .h 中:

#import <objc/runtime.h>

@interface Chair (Liking)

     @property (nonatomic, assign)BOOL liked;
 @end

在您的 .m 中:

#import "Chair+ChairCat.h"

@implementation Chair (Liking)

 -(BOOL)liked{

    return [ objc_getAssociatedObject( self, "_aliked" ) boolValue ] ;    
 }

-(void)setLiked:(BOOL)b{    
    objc_setAssociatedObject(self, "_aliked",  [ NSNumber numberWithBool:b ],OBJC_ASSOCIATION_RETAIN_NONATOMIC ) ;

 }

@end

然后在其他类的某个地方说 myViewController.m

#import "Chair+ChairCat.h"
- (void)viewDidLoad {
    /////
    Chair *chair = [[Chair alloc] init];
    [chair setLiked:NO];
}
于 2017-10-03T09:56:28.587 回答