NSInvocation返回值,但通过EXC_BAD_ACCESS使应用程序崩溃

我有一个数组,我正在迭代并寻找一个特定的标志。 如果标志值为零,我正在调用一个方法来生成一个调用对象并返callback用的结果。

我的代码结构如下

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); } } 

生成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; } 

在for循环中,没有方法调用NSInvocation([self ….]),循环只是执行正常,不会崩溃。 但是当我介绍调用NSInvocation的方法时,我能够看到NSLog的for循环打印预期NSArray的结果,但它崩溃与错误消息EXC_BAD_ACCESS。

即使NSInvocation返回正确的结果,我也无法弄清楚它为什么失败。 没有NSInvocation,for循环不会崩溃。

任何的意见都将会有帮助。

谢谢

我猜你正在使用ARC?

问题是与行[invocation getReturnValue:&resultSet];getReturnValue:只是将返回值的字节复制到给定的内存缓冲区中,而不pipetypes如何。 如果返回types是可保留的对象指针types,它不知道或关心内存pipe理。 由于resultSet是对象指针types的__strongvariables,因此ARC会假定已放入variables的任何值都被保留,因此在超出作用域时会释放它。 在这种情况下不是这样,所以它崩溃了。 (而且,你最初指向resultSet的数组将被泄漏,因为getReturnValue:覆盖该值而不释放它。为什么你甚至把这个variables指向一个对象呢?

解决的办法是,你必须给一个非保留types的指针getReturnValue: 或者:

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

要么:

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

是的,这只是发生在ARC。

我猜这是系统Bug。

例如:
【iPhone4s + iOS8.4】,【iphone 4 + iOS7.1】(crash),
【iPhone6 + iOS9.3】,【iphone 5 + iOS8.4.1】(通行证),

我的testing演示下载链接https://github.com/leopardpan/IssuesDemo

原来的代码

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

解决以下几点

情况1:

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

情况2:

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

情况3:

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

案例4:

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

build议使用case1,原则应该是@newacct说的
欢迎来讨论