Frage

Ich verwende Blöcke seit einiger Zeit, aber ich habe das Gefühl, dass es Dinge gibt, die ich bei der Speicherverwaltung sowohl in ARC- als auch in Nicht-ARC-Umgebungen vermisse.Ich habe das Gefühl, dass ein tieferes Verständnis dazu führen wird, dass ich viele Speicherlecks aufheben werde.

AFNetworking ist meine Hauptverwendung von Blöcken in einer bestimmten Anwendung.Meistens mache ich in einem Abschlusshandler einer Operation so etwas wie "[self.myArray addObject]".

Sowohl in ARC- als auch in nicht ARC-fähigen Umgebungen wird "Selbst" gemäß beibehalten dieser Artikel von Apple.

Das bedeutet, dass jedes Mal, wenn ein Abschlussblock einer AFNetworking-Netzwerkoperation aufgerufen wird, 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 Leckage-Tool als auch den statischen Analysator ausgeführt, damit ich Speicherlecks finden kann.Keiner zeigte irgendwelche.

Allerdings bin ich erst vor kurzem auf eine Warnung gestoßen, die ich nicht herausfinden konnte.Ich verwende ARC in diesem speziellen Beispiel.

Ich habe zwei Instanzvariablen, die den Abschluss und den Fehler 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 beschwert sich über die Zeile, die den failureBlock aufruft, wobei die Meldung "Selbst stark erfassen" in diesem Block wahrscheinlich zu einem Aufbewahrungszyklus führt.Ich glaube, Xcode ist richtig:der Fehlerblock behält self , und self hält seine eigene Kopie des Blocks, so dass keiner der beiden freigegeben wird.

Ich habe jedoch die folgenden Fragen / Beobachtungen.

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

2) Was ist im Allgemeinen die beste Vorgehensweise, um mit Blöcken sowohl in ARC- als auch in nicht ARC-fähigen Umgebungen zu arbeiten, wenn blöcke, die Instanzvariablen sind?Scheint, dass im Fall von Fertigstellungs- und Fehlerblöcken in AFNetworking diese beiden Blöcke sind nicht Instanzvariablen, damit sie wahrscheinlich nicht in die Kategorie der Aufbewahrungszyklen fallen, die ich oben beschrieben habe.Aber was kann getan werden, um Aufbewahrungszyklen wie den obigen zu vermeiden, wenn Fortschrittsblöcke in AFNetworking verwendet werden?

Ich würde gerne die Gedanken anderer Leute zu ARC und Nicht-ARC mit Blöcken und Problemen / Lösungen mit der Speicherverwaltung hören.Ich finde diese Situationen fehleranfällig und 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.

War es hilfreich?

Lösung

1) Wenn ich _failureblock (Fehler) in "self.failureblock (Fehler) ändere (ohne Anführungszeichen) Der Compiler hört auf, sich zu beschweren. Warum das? Ist das Ein Speicher dicht den Compiler fehlt?

Der Haltezyklus existiert in beiden Fällen. Wenn Sie iOS 5+ ansprechen, können Sie einen schwachen Bezug auf sich selbst weitergeben:

generasacodicetagpre.

Jetzt wird sich selbst nicht aufbewahrt, und wenn er gelöst wird, bevor der Rückruf aufgerufen wird, ist der Rückruf ein No-Op. Es ist jedoch möglich, dass es jedoch möglich ist, dass der Rückruf an einem Hintergrundgewinde aufgerufen wird, sodass dieses Muster gelegentliche Abstürze erstellen kann.

2) Im Allgemeinen, was ist die beste Praxis, um mit Blöcken in beiden zu arbeiten ARC- und NICHT-ARC-fähige Umgebungen, wenn Sie Blöcke verwenden Instanzvariablen? Scheint das im Fall von Fertigstellung und Misserfolg Blöcke in Afnetworking, diese beiden Blöcke sind nicht Instanzvariablen so Sie fallen wahrscheinlich nicht in die Kategorie der Haltezyklen, die ich oben beschrieben. Aber wenn Sie Fortschrittsblöcke in Afnetworking verwenden, Was kann getan werden, um zu vermeiden, dass Sie Zyklen wie den oben genannten halten?

Meistens denke ich, Es ist besser nicht zu Store-Blöcke in den Instanzvariablen . Wenn Sie den Block stattdessen von einer Methode in Ihrer Klasse zurücksenden, haben Sie immer noch einen Haltezyklus, aber es besteht jedoch nur aus der Zeit, in der das Verfahren auf den Zeitpunkt der Veröffentlichung des Blocks aufgerufen wird. Daher wird verhindert, dass Ihre Instanz während der Blockausführung gelöst wird, aber der Haltezyklus endet, wenn der Block freigegeben wird:

generasacodicetagpre.

Andere Tipps

Das bedeutet, dass immer dann, wenn ein Abschlussblock eines AFNetworking-Netzwerks operation wird aufgerufen, self wird in diesem Block beibehalten und freigegeben wenn dieser Block den Gültigkeitsbereich verlässt.

Nein, self wird vom Block beibehalten, wenn der Block erstellt wird.Und es wird freigegeben, wenn der Block freigegeben wird.

Ich glaube, Xcode ist richtig:der Fehlerblock behält sich selbst und Selbst bei hält seine eigene Kopie des Blocks, so dass keiner der beiden sein wird freigegeben.

Der fragliche Block, der behält self wird der Abschlussblock übergeben an setCompletionBlockWithSuccess. self enthält keinen Verweis auf diesen Block.Eher, self.operation (vermutlich eine Art von NSOperation) behält die Blöcke während der Ausführung bei.Es gibt also vorübergehend einen Zyklus.Wenn die Operation jedoch ausgeführt ist, wird der Zyklus unterbrochen.

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

Es sollte keinen Unterschied geben. self wird in beiden Fällen erfasst.Es ist nicht garantiert, dass der Compiler alle Fälle von Aufbewahrungszyklen erfasst.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top