NSInvocation延迟调用导致EXC_BAD_ACCESS的方法

时间:2014-10-24 05:23:37

标签: ios objective-c selector exc-bad-access nsinvocation

我试图在游戏结束时显示一条消息,显示玩家是否赢了。

以下是相关代码:

BOOL yes = YES;
NSString *winMessage = [NSString stringWithFormat:@"You win!"];
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(endGameWithMessage:win:par:)]];
[inv setSelector:@selector(endGameWithMessage:win:par:)];
[inv setTarget:self];
[inv setArgument:&winMessage atIndex:2];
[inv setArgument:&yes atIndex:3]; //this is the win BOOL (0 and 1 are explained in the link above)
[inv setArgument:&parBool atIndex:4]; //this is the par BOOL
[inv performSelector:@selector(invoke) withObject:nil afterDelay:0.1f];

这是endGameWithMessage方法签名:

- (void)endGameWithMessage:(NSString*)message win:(BOOL)win par:(BOOL)parBool

尽管直接调用代码(显然不会允许延迟)就像这样工作得很好,消息显示为预期并且不会导致任何崩溃:

[self endGameWithMessage:@"You win!" win:YES par:parBool];

尝试使用NSInvocation会导致endGameWithMessage:方法出现EXC_BAD_ACCESS崩溃。这是否意味着我以错误的方式将我的值传递给方法调用?

1 个答案:

答案 0 :(得分:0)

这两段代码有两点不同:

  1. 一个使用字符串文字@"You win!",另一个创建一个新的字符串对象。字符串文字是静态分配的,而不是内存管理的,因此使用字符串参数进行的任何不正确的内存管理都会影响分配的对象,而不会影响字符串文字。

  2. 更重要的是,NSInvocation是异步调用的,并且您没有要求调用保留[inv retainArguments];的参数。这意味着调用不会保留selfwinMessage,因为它应该异步使用它们。