Objective C-Speicherverwaltung mit Blöcken, ARC und Nicht-ARC

Ich benutze bereits seit einiger Zeit Blöcke, aber ich habe das Gefühl, dass mir bei der Speicherverwaltung in ARC- und Nicht-ARC-Umgebungen einige Dinge fehlen. Ich habe das Gefühl, dass ein tieferes Verständnis mich viele Speicherlecks zunichte machen wird.

AFNetworking ist meine Hauptverwendung von Blöcken in einer bestimmten Anwendung. Die meiste Zeit mache ich in einem Completion-Handler einer Operation so etwas wie "[self.myArray addObject]".

Sowohl in ARC- als auch in nicht ARC-fähigen Umgebungen wird "self" gemäß beibehaltendieser Artikel von Apple.

Dies bedeutet, dass beim Aufrufen eines Abschlussblocks einer AFNetworking-Netzwerkoperation self in diesem Block beibehalten und freigegeben wird, wenn dieser Block den Gültigkeitsbereich verlässt. Ich glaube, dass dies sowohl für ARC als auch für Nicht-ARC gilt. Ich habe sowohl das Tool "Lecks" als auch den Static Analyzer ausgeführt, damit ich möglicherweise Speicherlecks finde. Keiner zeigte einen.

Allerdings bin ich erst kürzlich auf eine Warnung gestoßen, die ich nicht herausfinden konnte. In diesem Beispiel verwende ich ARC.

Ich habe zwei Instanzvariablen, die den Abschluss und den Ausfall eines Netzwerkvorgangs anzeigen

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

Irgendwo im Code mache ich das:

[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 beklagt sich über die Zeile, die den failureBlock aufruft, wobei die Meldung "Capturing" self "in diesem Block wahrscheinlich zu einem Beibehaltungszyklus führt. Ich glaube, Xcode ist richtig: Der failure-Block behält self bei und self hält seine eigene Kopie von der Block, so wird keiner der beiden freigegeben.

Ich habe jedoch die folgenden Fragen / Bemerkungen.

1) Wenn ich _failureBlock (error) in "self.failureBlock (error)" (ohne Anführungszeichen) ändere, hört der Compiler auf, sich zu beschweren. Warum das? Ist dies ein Speicherverlust, den der Compiler vermisst?

2) Was ist im Allgemeinen die beste Vorgehensweise, um mit Blöcken in ARC- und nicht ARC-fähigen Umgebungen zu arbeiten, wenn Sie verwenden?Blöcke, die Instanzvariablen sind? Scheint, dass im Fall von Abschluss- und Fehlerblöcken in AFNetworking diese beiden Blöcke vorhanden sindnicht Instanzvariablen fallen daher wahrscheinlich nicht in die Kategorie der Retain-Zyklen, die ich oben beschrieben habe. Was kann man jedoch tun, um bei der Verwendung von Fortschrittsbausteinen in AFNetworking zu vermeiden, dass Zyklen wie die oben beschriebenen beibehalten werden?

Ich würde gerne die Gedanken anderer Leute über ARC und Nicht-ARC mit Blockaden und Problemen / Lösungen beim Speichermanagement hören. Ich finde diese Situationen fehleranfällig und ich halte eine Diskussion darüber für notwendig, um die Dinge zu klären.

Ich weiß nicht, ob es darauf ankommt, aber ich verwende Xcode 4.4 mit der neuesten LLVM.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage