ios objective-c nsinvocation

ios - NSInvocation devuelve valor pero hace que la aplicación se bloquee con EXC_BAD_ACCESS



objective-c (2)

Tengo una matriz que estoy iterando y buscando una bandera en particular. Si el valor del indicador es nulo, estoy llamando a un método que genera un objeto de invocación y devuelve el resultado de la invocación.

Mi estructura de código es la siguiente

for(NSString *key in [taxiPlanes allKeys]) { Plane *currentPlane = [taxiPlanes objectForKey:key]; if(currentPlane.currentAction == nil) { NSString *selector = [[currentPlane planeTakeoffSequence] firstObject]; currentPlane.currentAction = selector; // Calling for NSInvocation in [self ...] NSArray *action = [NSArray arrayWithArray:[self operationFromTakeoffAction:currentPlane.currentAction AtPoint:currentPlane.position]]; NSLog(@"%@",action); } }

Método que genera NSInvocation

-(NSArray *) operationFromTakeoffAction:(NSString *) action AtPoint:(CGPoint) flightPoint { NSMethodSignature *methodSignature = [FlightOperations instanceMethodSignatureForSelector:NSSelectorFromString(action)]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; [invocation setTarget:fOps]; [invocation setSelector:NSSelectorFromString(action)]; [invocation setArgument:&flightPoint atIndex:2]; NSArray *resultSet = [NSArray alloc]init]; [invocation invoke]; [invocation getReturnValue:&resultSet]; return resultSet; }

En el bucle for, sin el método llamado a NSInvocation ([self ....]), el bucle simplemente se ejecuta correctamente y no se bloquea. Pero cuando introduzco el método para invocar NSInvocation, puedo ver el inicio de sesión de NSLog para el resultado de NSArray esperado, pero se bloquea con el mensaje de error EXC_BAD_ACCESS.

No puedo averiguar por qué falla, a pesar de que NSInvocation devuelve un resultado adecuado. Sin NSInvocation, el bucle no se bloquea.

Cualquier sugerencia sería útil.

Gracias


Supongo que estás usando ARC?

El problema es con la línea [invocation getReturnValue:&resultSet]; . getReturnValue: simplemente copia los bytes del valor de retorno en el búfer de memoria dado, independientemente del tipo. No sabe o le importa la administración de memoria si el tipo de retorno es un tipo de puntero de objeto que se puede volver a guardar. Dado que resultSet es una variable __strong del tipo de puntero de objeto, ARC asume que cualquier valor que se haya colocado en la variable se ha conservado y, por lo tanto, lo liberará cuando salga de su alcance. Eso no es cierto en este caso, por lo que se bloquea. (Además, la matriz a la que originalmente tenía como resultSet el Conjunto de getReturnValue: , ya que getReturnValue: sobrescribe ese valor sin liberarlo. Por qué incluso hizo que ese punto de variable para un objeto en primer lugar esté fuera de mi getReturnValue: ).

La solución es que debe getReturnValue: un puntero a un tipo no retenido para getReturnValue: Ya sea:

NSArray * __unsafe_unretained tempResultSet; [invocation getReturnValue:&tempResultSet]; NSArray *resultSet = tempResultSet;

o:

void *tempResultSet; [invocation getReturnValue:&tempResultSet]; NSArray *resultSet = (__bridge NSArray *)tempResultSet;


Sí, eso acaba de suceder en el ARC。

Supongo que este es el error del sistema.

Por ejemplo:
【IPhone4s + iOS8.4】 、 【iphone 4 + iOS7.1 (bloqueo),
【IPhone6 ​​+ iOS9.3】 、 【iphone 5 + iOS8.4.1】 (pase),

Mi enlace de descarga de demostración de prueba https://github.com/leopardpan/IssuesDemo

El codigo original

NSArray *resultSet = [NSArray alloc]init]; [invocation invoke]; [invocation getReturnValue:&resultSet];

Para resolver lo siguiente

caso 1:

void *temp = NULL; [invocation invoke]; [invocation getReturnValue:&temp]; NSArray *resultSet = (__bridge NSArray*)temp;

caso 2 :

__weak NSArray *resultSet = [NSArray alloc]init]; [invocation invoke]; [invocation getReturnValue:&resultSet];

caso 3:

__autoreleasing NSArray *resultSet = [NSArray alloc]init]; [invocation invoke]; [invocation getReturnValue:&resultSet];

caso 4:

__unsafe_unretained NSArray *resultSet = [NSArray alloc]init]; [invocation invoke]; [invocation getReturnValue:&resultSet];

Recomendado para usar case1, el principio debe ser @newacct dijo
Bienvenido a discutir