2014-10-24 1 views
0

Я пытаюсь отобразить сообщение в конце игры, которое показывает, выиграл ли игрок.NSInvocation для задержки вызова метода, вызывающего EXC_BAD_ACCESS

Вот соответствующий код:

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 приводит к сбою EXC_BAD_ACCESS в методе endGameWithMessage :. Означает ли это, что я передаю свои значения методу вызова неправильным образом?

ответ

0

Есть два различия между этими двумя частями кода:

  1. One использует строку буквального @"You win!", другой создает новый объект строки. Строковые литералы распределяются статически, а не управляются памятью, поэтому любое неправильное управление памятью со строковым параметром влияет на выделенный объект, а не на строковый литерал.

  2. Что еще более важно, асинхронно вызывается NSInvocation, и вы не запрашивали вызов для сохранения аргументов с помощью [inv retainArguments];. Это означает, что self и winMessage не сохраняются при вызове, как это необходимо, чтобы использовать их асинхронно.

+0

Благодарим вас за поддержку, особенно за то, что вы уловили недостаток [inv retainArguments] ;. Ваша гипотеза была правильной, добавив вызов keepArguments после того, как все мои аргументы зафиксировали мой сбой EXC_BAD_ACCESS, потому что, как вы сказали, сообщение отправлялось с аргументами NULL. – MachCUBED