2012-05-08 21 views
9

我试图扩展cocos2d的SimpleAudioEngine的功能,以便能够连续播放几个音效作为某种链。我试图用扩展名来做到这一点。但是我现在意识到,我可能还需要一个iVar来记住所有声音文件的名称,并且要记住当前正在播放的声音。Objective-C类别和新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]; 

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

+1

为什么不将SimpleAudioEngine子类化? – lawicko

+0

[Objective-C:属性在类别](http:// stackoverflow。com/questions/8733104/objective-c-property-in-category) – hfossli

回答

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 

(标准免责声明适用,我在浏览器中输入了该信息,但没有对其进行测试,但之前我已使用过该技术。)

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

+0

我忘记说我在iOS上工作。我现在将这些信息添加到标签。在iOS上,这种方法被禁止。你知道是否还有办法实现这个目标吗?还是需要创建一个提供我想要的功能的新类? –

+0

@gebirgsbaerbel:禁止在iOS?你是从哪里听来的? – Chuck

+0

@在文档中表示该功能在MacOS10.6及更新版本上可用。此外,我试了一下,我基本上得到的错误,这两种方法是未知的。包含它们的头文件在iOS上似乎不存在。也许我错过了什么? –

-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]; 
}