Aar*_*man 15 objective-c instruments objective-c-blocks automatic-ref-counting
所以我正在使用递归块.我理解,对于要递归的块,它需要以__block关键字开头,并且必须将其复制,以便将其放在堆上.但是,当我这样做时,它显示为仪器中的泄漏.有谁知道为什么或如何绕过它?
请注意,在下面的代码中,我已经引用了许多其他块,但它们都不是递归的.
__block NSDecimalNumber *(^ProcessElementStack)(LinkedList *, NSString *) = [^NSDecimalNumber *(LinkedList *cformula, NSString *function){
LinkedList *list = [[LinkedList alloc] init];
NSDictionary *dict;
FormulaType type;
while (cformula.count > 0) {
dict = cformula.pop;
type = [[dict objectForKey:@"type"] intValue];
if (type == formulaOperandOpenParen || type == formulaListOperand || type == formulaOpenParen) [list add:ProcessElementStack(cformula, [dict objectForKey:@"name"])];
else if (type == formulaField || type == formulaConstant) [list add:NumberForDict(dict)];
else if (type == formulaOperand) [list add:[dict objectForKey:@"name"]];
else if (type == formulaCloseParen) {
if (function){
if ([function isEqualToString:@"AVG("]) return Average(list);
if ([function isEqualToString:@"MIN("]) return Minimum(list);
if ([function isEqualToString:@"MAX("]) return Maximum(list);
if ([function isEqualToString:@"SQRT("]) return SquareRoot(list);
if ([function isEqualToString:@"ABS("]) return EvaluateStack(list).absoluteValue;
return EvaluateStack(list);
} else break;
}
}
return EvaluateStack(list);
} copy];
NSDecimalNumber *number = ProcessElementStack([formula copy], nil);
Run Code Online (Sandbox Code Playgroud)
更新 因此,在我自己的研究中,我发现问题显然与该块使用的其他块的引用有关.如果我做这样简单的事情,它不会泄漏:
__block void (^LeakingBlock)(int) = [^(int i){
i++;
if (i < 100) LeakingBlock(i);
} copy];
LeakingBlock(1);
Run Code Online (Sandbox Code Playgroud)
但是,如果我在此添加另一个块,它会泄漏:
void (^Log)(int) = ^(int i){
NSLog(@"log sub %i", i);
};
__block void (^LeakingBlock)(int) = [^(int i){
Log(i);
i++;
if (i < 100) LeakingBlock(i);
} copy];
LeakingBlock(1);
Run Code Online (Sandbox Code Playgroud)
我已经尝试将__block关键字用于Log()并尝试复制它,但它仍然泄漏.有任何想法吗?
更新2 我找到了一种防止泄漏的方法,但这有点麻烦.如果我将传入的块转换为弱id,然后将弱id转换回块类型,我可以防止泄漏.
void (^Log)(int) = ^(int i){
NSLog(@"log sub %i", i);
};
__weak id WeakLogID = Log;
__block void (^LeakingBlock)(int) = [^(int i){
void (^WeakLog)(int) = WeakLogID;
WeakLog(i);
if (i < 100) LeakingBlock(++i);
} copy];
LeakingBlock(1);
Run Code Online (Sandbox Code Playgroud)
当然有更好的方法吗?
Aar*_*man 11
好吧,我自己找到了答案......但感谢那些试图提供帮助的人.
如果您在递归块中引用/使用其他块,则必须将它们作为弱变量传递.当然,__ weak仅适用于块指针类型,因此您必须先键入它们.这是最终的解决方案:
typedef void (^IntBlock)(int);
IntBlock __weak Log = ^(int i){
NSLog(@"log sub %i", i);
};
__block void (^LeakingBlock)(int) = ^(int i){
Log(i);
if (i < 100) LeakingBlock(++i);
};
LeakingBlock(1);
Run Code Online (Sandbox Code Playgroud)
上面的代码不泄漏.
归档时间: |
|
查看次数: |
3724 次 |
最近记录: |