【问题标题】:Objective-C Category and new iVarObjective-C 类别和新的 iVar
【发布时间】:2012-05-08 16:26:29
【问题描述】:

我尝试扩展 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];

如果有其他方法可以产生相同/相似的结果,我也将非常感激。

【问题讨论】:

标签: iphone objective-c ios cocos2d-iphone


【解决方案1】:

您不能将实例变量(或合成的@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

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

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

【讨论】:

  • 我忘了说明我正在使用 iOS。我现在将此信息添加到标签中。在 iOS 上,这种方法是被禁止的。你知道是否还有办法实现这一点,还是我需要创建一个新类来提供我想要的功能?
  • @gebirgsbaerbel:禁止在 iOS 上使用?你从哪里听到的?
  • @Chuck 在文档中说该功能在 MacOS10.6 及更高版本上可用。我也试过了,我基本上得到了这两种方法都不知道的错误。 iOS 上似乎不存在包含它们的头文件。也许我错过了什么?
  • 您需要在使用 Objective-C 运行时函数(包括关联引用函数)的文件中#import &lt;objc/runtime.h&gt;。它们在 iOS 上可用。如果您查看 runtime.h,您会发现它们在 OS X 10.6 及更高版本以及 iOS 3.1 及更高版本中可用。
  • 啊,谢谢,我找不到正确的导入,即使它位于代码的顶部...有时我有点盲目
【解决方案2】:

您不能添加 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];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多