gpt4 book ai didi

objective-c - CCCallFunc 和 ARC

转载 作者:行者123 更新时间:2023-12-02 22:30:10 24 4
gpt4 key购买 nike

这是我的问题 我试图在 cocos2d for iphone 中为 Action 序列创建一个回调函数,但我一直收到错误的访问错误。

我在这里创建我的回调

id myCallFunc = [CCCallFuncND actionWithTarget:self.delegate selector:@selector(playerAttack:data:) data:(__bridge void *)([[PlayerAttackPacket alloc] initWithPlayer:@"" attackChoice: [NSNumber numberWithInt: item.tag]]) ]; // to call our method

这是被回调的函数,当转换数据时,编译器说访问错误。

-(void) playerAttack:(id)sender data:(void *)data
{
PlayerAttackPacket* packet = (__bridge PlayerAttackPacket*)data;
BattleModel *model = [BattleModel sharedInstance];
int choice = packet.attackChoice.intValue;
NSString * players = packet.player;
}

播放器数据包:

@interface PlayerAttackPacket : NSObject {
NSString * player;
NSNumber * attackChoice;
}

@property (nonatomic, retain) NSString * player;
@property (nonatomic, retain) NSNumber * attackChoice;
-(id) initWithPlayer: (NSString*)_player attackChoice: (NSNumber*)choice;
@end

@implementation PlayerAttackPacket
@synthesize player,attackChoice;

-(id) initWithPlayer: (NSString*)_player attackChoice: (NSNumber*)choice
{
if((self=[super init]))
{
self.player = _player;
self.attackChoice = choice;
}
return self;
}
@end

谁能告诉我我做错了什么? =(。我的感觉是它与 ARC 有关,但我不确定。

最佳答案

为了可读性,这里是你的 call func 方法重新格式化:

void* data = (__bridge void*)[[PlayerAttackPacket alloc] initWithPlayer:@"" 
attackChoice: [NSNumber numberWithInt: item.tag]];
id myCallFunc = [CCCallFuncND actionWithTarget:self.delegate
selector:@selector(playerAttack:data:) data:data ];

你做的是这样的:

  • 分配新对象
  • bridge 将其转换为 void*
  • 将其传递给 CCCallFuncND

ARC 看到/做的是这样的:

  • 分配新对象
  • 新对象桥投(忽略)
  • 对象在调用 func 后超出范围
  • 释放对象

您没有保留对该对象的强引用,因此它会在执行选择器时释放。请不要使用 Ben 的建议,我知道它有效,但它也很危险,因为只要 call func 操作实际上没有执行选择器,它就会泄漏内存,即停止操作/序列或调用时更改场景func 仍在运行,等待执行选择器。

您可以通过两种方式解决此问题:

  • 保持对新对象的强引用直到选择器被执行,即作为类的实例变量
  • 改为使用 CCCallBlock

一定要使用方 block !它避免了内存管理问题,您也不必对该对象有强引用。事实上,您甚至不必将其传递给 block !这是它的工作原理:

PlayerAttackPacket* packet = [[PlayerAttackPacket alloc] initWithPlayer:@"" 
attackChoice: [NSNumber numberWithInt: item.tag]];

id myCallBlock = [CCCallBlock actionWithBlock:^{

// no bridge casting required, packet variable is accessible within the block
// no memory management needed, block copies packet and keeps it alive
BattleModel *model = [BattleModel sharedInstance];
int choice = packet.attackChoice.intValue;
NSString * players = packet.player;
}];

现在我有点猜测,但在我看来,您创建 PlayerAttackPacket 类只是为了将几个参数传递到 CCCallFuncND。您也可以使用 block 跳过它!

NSString* player = @"player1";

id myCallBlock = [CCCallBlock actionWithBlock:^{

// whatever variables you need from the surrounding scope, you can just use
// them as if they were local variables in the block!
int choice = item.tag;
NSString * players = player;
}];

block 非常方便,并且可以更好地与 ARC 配合使用。使用积木!重复:use blocks .

关于objective-c - CCCallFunc 和 ARC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12399425/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com