iOS 4 Blöcke und behalten zählt
Ich fange gerade mit Blöcken und Grand Central Dispatch. Ich habe gesagt (und gelesen in den Apple-Dokumentation), dass alle referenzierten Objekts innerhalb eines Blocks wird beibehalten.
Zum Beispiel:
^{
self.layer.transform = CATransform3DScale(CATransform3DMakeTranslation(0, 0, 0), 1, 1, 1);
self.layer.opacity = 1;
}
"selbst" wird beibehalten, so dass es Lecks. Um das zu vermeiden, muss ich ordnen Sie sich selbst zu:
__block Object *blockSelf = self;
und verwenden Sie dann blockSelf
statt self
in meinem block.
Meine Frage ist: was passiert, wenn Ihr block hat viel mehr code und Referenzen mehrere Objekte? Muss ich zuordnen, Sie alle zu __block
Objekte? Zum Beispiel:
^{
[self doSomething];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"prevName == %@", artistName];
[request setEntity:entity];
[request setPredicate:predicate];
Object *newObject = [[Object alloc] init];
[someArray addObject];
[newObject release];
}
- möglicherweise Verwandte: stackoverflow.com/questions/4352561/...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nicht. Das problem tritt auf, wenn der block behält ein Objekt, das behält es. Ihr block wird behalten, jedes Objekt, auf die es verweist, außer für diejenigen, versehen mit
__block
. Daher:self
behältblock
, undblock
implizit behältself
. Dies wird auchpassieren, wenn Sie auf Instanz-Variablen von
self
.Variablen versehen mit
__block
sind veränderlich (für Zeiger, dass ist, dieAdresse, auf die Sie verweisen, kann geändert werden); als Ergebnis, es macht keinen Sinn
behalten, dass das Objekt, da Sie benötigen, um die Behandlung dieses Objekt als lokale variable
(wie in, es kann neu zugewiesen werden, Auswirkungen auf ein Objekt außerhalb des Bereichs der block). So
__block
nicht bekommen, bleibt blockiert.Aber, jetzt können Sie laufen in unvorhergesehenen Problemen, wenn Sie versuchen, verwenden Sie diesen block in einer bestimmten Weise. Zum Beispiel, wenn Sie sich entscheiden, verzögern Sie den Aufruf dieser block irgendwie, und
self
wurde freigegeben durch die Zeit, die Sie ausführen, die blockieren, kann Ihr Programm zum Absturz bringen, da Sie das senden einer Nachricht an ein Objekt freigegeben. Was Sie brauchen, dann ist das eine schwache Referenz, die nicht out-of-the-box auf dem nicht-garbage-collected Umgebung!Eine Lösung ist die Verwendung MAZeroingWeakRef zu wickeln Sie Ihre block; diese wird null, der Zeiger so, dass Sie am Ende nur das senden von Nachrichten an
nil
sollten Sie versuchen, die Nachrichtself
nachself
wurde aufgehoben:Habe ich auch umgesetzt schwache Referenz-wrapper in Objective-C++, das bietet den Vorteil, eine leichte syntax:
Weil
js::weak_ref
ist eine Vorlage-Klasse, erhalten Sie praktisch strong-typing (das heißt, Sie erhalten Warnungen bei der Kompilierung-Zeit, wenn Sie versuchen, senden Sie dem Verweis auf eine Mitteilung, die es nicht erscheint, um zu reagieren). Aber Mike ' sMAZeroingWeakReference
ist viel mehr Reife als meine, also ich würde vorschlagen, mit sein, es sei denn, Sie möchten Holen Sie sich Ihre Hände schmutzig zu machen.Mehr zu Lesen über Probleme mit
__block
und der use-case für schwache Verweise, Lesen Vermeidung von retain-Zyklen mit Blöcken, einem richtigen Weg und Jonathan Rentzsch Antwort.__block
sindconst
-kopiert (für Objekte, das heißt eine Kopie des Zeigers hergestellt ist, nicht eine Kopie des Objekts); 2. referenzierte Objekte nicht markiert__weak
oder__block
beibehalten werden.__weak
sonst =>__block
.Ich würde sagen, es hängt davon ab, was du tust mit deinem block. Wenn Sie nicht speichern Sie es irgendwo und verwenden Sie es in der definition Ort (wie das Sortieren ein array mit einem block), dann wird es veröffentlicht, zusammen mit der Variablen verwiesen wird, ist es innen (seit seiner Erstellung im Stapel und ist die Bezeichnung für autorelease). Wenn Sie speichern es irgendwo (ein array, Wörterbuch oder wahrscheinlich übergeben Sie den block, um einige der anderen Funktion)
copy
den block und das Gleichgewicht mitautorelease
vor der übergabe zusammen.