'da Objective-C sızıntısında yinelenen bloklar Bu yüzden özyinelemeli blokları kullanıyorum. Bir bloğun özyinelemesinin __block anahtar sözcüğünden önce gelmesi gerektiğini anlıyorum ve kopyalanmalı, böylece yığının üzerine yerleştirilebilir. Ancak, bunu yaptığımda, Enstrümanlarda bir sızıntı olarak ortaya çıkıyor. Herkesin neden ya da etrafından nasıl geçebileceğini bilen var mı? Ben diğer blokların bir sürü başvurular var ama bunların hiçbiri özyinelemeli aşağıda ARC
kodunda unutmayınız.__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);
GÜNCELLEME Yani kendi araştırmalarında ben sorunu olasılıkla bu blok kullanan diğer bloklara referanslarla ilgisi var olduğunu keşfettik. Böyle basit bir şey yaparsanız, su almaması:
__block void (^LeakingBlock)(int) = [^(int i){
i++;
if (i < 100) LeakingBlock(i);
} copy];
LeakingBlock(1);
Ancak, bu bir başka blok eklemek, eğer sızıntı yapar: Ben __block kullanarak denedim
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);
Log() için anahtar kelime ve ayrıca kopyalamayı denedi, ancak hala sızdırıyor. Herhangi bir fikir?
UPDATE 2 Sızıntıyı önlemenin bir yolunu buldum, ancak biraz zahmetli. Geçilen bloğu zayıf bir kimliğe dönüştürürsem ve zayıf kimliği bir blok türüne geri döndürürsem, sızıntıyı önleyebilirim.
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);
Şüphesiz daha iyi bir yolu var mı?
sayesinde ben de blok kopyalamak zorunda hakkında duymadım. Bununla birlikte, daha yeni bir LLVM'nin "LeakingBlock'u bu blokta güçlü bir şekilde yakalama olasılığının bir tutma döngüsüne yol açması muhtemel" çağrısında bir uyarı verdiği anlaşılmaktadır.Derleyiciyi rahatlatmak için bulduğum tek yol, aşağıdaki cevaba biraz benzer bir şekilde blok için ayrı bir zayıf ptr kullanmaktır; En son derleyiciyi denedikten sonra aldığınızı görmek isterim. –
@smallduck Başlangıçta, 'copy' kullandım çünkü bloğun yığından yığına kopyalanmasını sağlıyor. Bir süre için iyi çalıştı ve ben de derleyici "özyinelemeli" hata var. "Kopyala" kodumdan kaldırdım (cevabımda yansıttığım gibi) ve işe yaradı (daha önce EXC_BAD_ACCESS olsun). Apple'ın "__block" anahtar sözcüğünü yerine yığında blok oluşturmak için değiştirdiğini tahmin ediyorum yığın ... ama bu sadece bir tahmin. –
@smallduck Truthfully, özyineleme için bloklar kullanarak verdim Evet, bu yapılabilir ama biraz can sıkıcı ve çok fazla tuzak var. Döngüleri (ki bu da yineleme ile çok kötü olabilir) ve okunması zorlaşır.Çünkü ben genellikle yineleme yapmak için yöntemler/işlevlerle uğraşırız –