我試圖將塊參數傳遞給NSInvocation
,但該應用程序崩潰。該調用發出網絡請求並調用成功或失敗塊。我認爲問題是在網絡請求完成之前塊已經交易。我設法讓它與一些Block_copy
hackery一起工作,並且它不使用工具報告任何泄漏。帶塊參數的NSInvocation
問題: - 即使靜態分析儀或儀器未報告泄漏,是否有泄漏存在? - 有沒有更好的方法來「保留」該塊?
// 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
forwardInvocation:
)
NSInvocation
→NSProxy
→method1
→methodN
methodN
取決於HTTP最終調用的成功或失敗塊響應。
我需要在每個階段複製塊嗎?上面的例子是關於第一個NSInvocation
。在每個適當的步驟中,我是否也需要[invocation retainArguments];
?我正在使用ARC。
我試了successBlock = [successBlock cop Y];和errorBlock = [errorBlock copy];但是我得到了與此錯誤相同的崩潰:地址不包含指向對象文件 中某個部分的部分。正如我所提到的那樣,添加Block_copy行可以防止崩潰,但我不確定它們是否會泄漏內存。 – pshah
您目前使用的'Block_copy'沒有記錄的效果。你所看到的是,由有問題的'invoke'引起的未定義結果具有不同的未定義效果。這不是一個真正的解決方案。甚至殭屍也不會幫助你在這裏進行調試,因爲它們不能保持堆棧對象的人爲活動 - 一旦堆棧增長回來,它將覆蓋它們。 – Tommy
我的印象是,調用Block_copy強制將塊保存在堆而不是堆棧上。而且,我仍然無法弄清楚爲什麼傳遞[successBlock copy]而不是successBlock來調用不起作用。 – pshah