Objective-C类别和新的iVar

时间:2012-05-08 16:26:30

标签: iphone objective-c ios cocos2d-iphone

我尝试扩展cocos2d的SimpleAudioEngine的功能,能够一个接一个地播放几种音效作为某种链。我尝试使用扩展程序执行此操作。但是我现在意识到我可能还需要一个iVar来记住所有声音文件的名称,还有一个要记住当前正在播放的声音。

但似乎我无法在类别中添加iVars。相反,我尝试使用扩展,但似乎它们需要在类的原始.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

或者,我尝试将iVars定义为属性,将进行编译。但是我既不能合成它们,也不能将它们绑定到任何方法上。

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

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

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

2 个答案:

答案 0 :(得分:22)

你是不对的,你不能将实例变量(或合成的@properties)添加到一个类别。您可以使用Objective-C运行时对Associative References

的支持来解决此限制

这样的事情:

在你的.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

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

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

答案 1 :(得分:-1)

您无法添加iVars,但可以添加属性变量。 如下所示:

在你的.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];
}