我尝试扩展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];
如果有另一种产生相同/类似结果的方法,我也会非常感激。
答案 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];
}