Obiektywne zarządzanie pamięcią C za pomocą bloków, ARC i innych niż ARC

Używam bloków już od jakiegoś czasu, ale czuję, że brakuje mi zarządzania pamięcią zarówno w środowiskach ARC, jak i innych. Czuję, że głębsze zrozumienie spowoduje, że stracę wiele przecieków pamięci.

AFNetworking to moje główne zastosowanie bloków w konkretnej aplikacji. Przez większość czasu, wewnątrz procedury obsługi operacji wykonuję coś takiego jak „[self.myArray addObject]”.

W środowiskach ARC i innych niż ARC „self” zostanie zachowane zgodnie zten artykuł od Apple.

Oznacza to, że za każdym razem, gdy wywoływany jest blok zakończenia operacji sieciowej AFNetworking, samoobsługa jest zachowywana w tym bloku i zwalniana, gdy ten blok wychodzi poza zakres. Uważam, że dotyczy to zarówno ARC, jak i non-ARC. Uruchomiłem zarówno narzędzie przecieków, jak i analizator statyczny, aby wykryć wycieki pamięci. Żaden nie pokazał.

Jednak dopiero niedawno natknąłem się na ostrzeżenie, którego nie mogłem zrozumieć. Używam ARC w tym konkretnym przykładzie.

Mam dwie zmienne instancji, które wskazują na zakończenie i niepowodzenie operacji sieciowej

@property (nonatomic, readwrite, copy) SFCompletionBlock completionBlock;
@property (nonatomic, readwrite, copy) SFFailureBlock failureBlock;
@synthesize failureBlock = _failureBlock;
@synthesize operation = _operation;

Gdzieś w kodzie robię to:

[self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id
                                                    responseObject) {
NSError *error = [NSError errorWithDomain:@"com.test" code:100 userInfo:@{@"description": @"zero results"}];
            _failureBlock(error);
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"nothing");
        }];

Xcode skarży się na linię, która wywołuje awarię Blokada, z komunikatem „Mocne przechwytywanie siebie” w tym bloku prawdopodobnie spowoduje cykl zatrzymania. Uważam, że Xcode ma rację: blok awarii zachowuje siebie, a sam posiada własną kopię blok, więc żaden z nich nie zostanie zwolniony.

Mam jednak następujące pytania / uwagi.

1) Jeśli zmienię _failureBlock (błąd) na „self.failureBlock (błąd)” (bez cudzysłowów), kompilator przestanie narzekać. Dlaczego? Czy to przeciek pamięci, którego kompilator nie trafia?

2) Ogólnie rzecz biorąc, jaka jest najlepsza praktyka podczas pracy z blokami w środowiskach ARC i innych niż ARCbloki będące zmiennymi instancji? Wygląda na to, że w przypadku zakończenia i blokowania błędów w AFNetworking te dwa bloki sąnie zmienne instancji, więc prawdopodobnie nie należą do kategorii zachowujących cykli, które opisałem powyżej. Ale kiedy wykorzystujemy bloki postępu w AFNetworking, co można zrobić, aby uniknąć zachowywania cykli takich jak powyżej?

Chciałbym usłyszeć myśli innych ludzi na temat ARC i non-ARC z blokami i problemami / rozwiązaniami z zarządzaniem pamięcią. Uważam, że te sytuacje są podatne na błędy i czuję, że konieczna jest dyskusja na ten temat.

Nie wiem, czy to ma znaczenie, ale używam Xcode 4.4 z najnowszym LLVM.

questionAnswers(2)

yourAnswerToTheQuestion