我正在尝试将块参数传递给 a NSInvocation
,但应用程序崩溃了。调用发出网络请求并调用成功或失败块。我认为问题在于在网络请求完成之前块被释放。我设法让它与一些Block_copy
黑客一起工作,并且它没有使用 Instruments 报告任何泄漏。
问题: - 即使静态分析仪或仪器没有报告泄漏,是否可能存在泄漏?- 有没有更好的方法来“保留”块?
// Create the NSInvocation
NSMethodSignature *methodSignature = [target methodSignatureForSelector:selector];
NSInvocation* invoc = [NSInvocation invocationWithMethodSignature:methodSignature];
[invoc setTarget:target];
[invoc setSelector:selector];
// Create success and error blocks.
void (^successBlock)(id successResponse) = ^(id successResponse) {
// Some success code here ...
};
void (^errorBlock)(NSError *error) = ^(NSError *error) {
// Some failure code here ...
};
/*
Without the two Block_copy lines, the block gets dealloced too soon
and the app crashes with EXC_BAD_ACCESS
I tried [successBlock copy] and [failureBlock copy] instead,
but the app still crashes.
It seems like Block_copy is the only way to move the block to the heap in this case.
*/
Block_copy((__bridge void *)successBlock);
Block_copy((__bridge void *)errorBlock);
// Set the success and failure blocks.
[invoc setArgument:&successBlock atIndex:2];
[invoc setArgument:&errorBlock atIndex:3];
[invoc retainArguments]; // does not retain blocks
// Invoke the method.
[invoc invoke];
更新:我将代码更新到下面。块是NSMallocBlocks
,但应用程序仍然崩溃。
// Create success and error blocks.
int i = 0;
void (^successBlock)(id successResponse) = ^(id successResponse) {
NSLog(@"i = %i", i);
// Some success code here ...
};
void (^errorBlock)(NSError *error) = ^(NSError *error) {
NSLog(@"i = %i", i);
// Some failure code here ...
};
/*** Both blocks are NSMallocBlocks here ***/
// Set the success and failure blocks.
void (^successBlockCopy)(id successResponse) = [successBlock copy];
void (^errorBlockCopy)(NSError *error) = [errorBlock copy];
/*** Both blocks are still NSMallocBlocks here - I think copy is a NoOp ***/
// Set the success and failure blocks.
[invoc setArgument:&successBlockCopy atIndex:2];
[invoc setArgument:&errorBlockCopy atIndex:3];
[invoc retainArguments]; // does not retain blocks
// Invoke the method.
[invoc invoke];
块在链中传递如下:
NSInvocation
→ NSProxy
(NSInvocation
使用forwardInvocation:
) → method1
→methodN
methodN
最终根据 HTTP 响应调用成功或失败块。
我需要在每个阶段复制块吗?上面的例子是在谈论第一个NSInvocation
. 我是否也需要[invocation retainArguments];
在每个适当的步骤?我正在使用ARC。