Sie sollten nichts schwach erfassen, nur weil Sie eine Warnung vom Compiler erhalten; Die Compilerwarnung ist nur raten; Es weiß nicht, wie die Methoden, die Sie aufrufen, die Referenzen bilden. Sie sollten dies nur tun, wenn Sie die Architektur der Referenzen verstehen und feststellen, dass ein Zyklus vorliegt, und feststellen, dass das Erfassen einer schwachen Referenz stattdessen das beabsichtigte Verhalten beibehält. Sie haben uns den Code -doSomethingWithBlock:
nicht angezeigt. Es würde nur einen Retain-Zyklus erzeugen, wenn es innerhalb dieser Methode den Block einer Eigenschaft oder Instanzvariable von self
zuweist. Tut es das oder nicht? Wenn nicht, dann gibt es keinen Rückhaltezyklus und es gibt keinen Sinn dafür, dass der äußere Block self
schwach erfasst.
Angenommen, der äußere Block, der self
schwach erfasst, ist richtig, die Beispiele, bei denen der äußere Block self
stark erfasst, kommen nicht in Frage. Die verbleibenden Fragen würden lauten, ob der innere Block self
(oder welche Version von self
, beispielsweise strongSelf
, angemessen ist) stark erfassen sollte. Mit anderen Worten, ob würden Sie so etwas wie dieses:
__weak __typeof(self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[object doSomethingElseWithBlock:^{
[strongSelf doYetAnotherThing];
}];
}
}];
oder etwas ähnliches:
__weak __typeof(self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[object doSomethingElseWithBlock:^{
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doYetAnotherThing];
}
}];
}
}];
Auch hier ist die wichtigste Frage, um zu bestimmen, ob es einen Zyklus, wenn der Innenblock erfasst behalten ist self
stark. Es würde nur einen Retain-Zyklus geben, wenn [object doSomethingElseWithBlock:...
den Block irgendwie einer Eigenschaft oder Instanzvariablen von self
zuweist. Aber wie könnte es sein? Die Methode wird unter object
, nicht self
aufgerufen. Die Methode erhält self
in keiner Weise.Wenn nicht etwas Kompliziertes vor sich geht, wird die Methode keiner Eigenschafts- oder Instanzvariablen von self
zugewiesen, so dass es unwahrscheinlich ist, einen Retain-Zyklus zu erstellen. Dies bedeutet, dass der innere Block, der self
schwach erfasst, nicht notwendig ist, um einen Rückhaltezyklus zu verhindern.
Aber ob der innere Block self
schwach oder stark erfasst, könnte das Verhalten beeinflussen. Wenn nämlich der innere Block self
schwach erfasst, könnte self
zum Zeitpunkt der Ausführung des Blocks freigegeben werden. In diesem Fall wird [strongSelf doYetAnotherThing];
nicht ausgeführt, wohingegen wenn der innere Block self
stark erfasst würde, würde self
am Leben erhalten und [strongSelf doYetAnotherThing];
würde ausgeführt . Es kommt also darauf an, was -doYetAnotherThing
tut. Wenn es eine UI-Operation unter self
ausführt, bei der es sich um eine UI-Ansicht oder etwas handelt, macht es keinen Unterschied, ob Sie es in einer Ansicht ausführen, die nicht mehr angezeigt wird. Aber wenn es zum Beispiel etwas an das Netzwerk oder etwas sendet, kann es einen großen Unterschied machen, ob es ausgeführt wird oder nicht.
Wird der Block an irgendeiner Stelle von selbst kopiert oder beibehalten? Oder wird es indirekt von einem anderen Objekt erhalten, das das Selbst behält? Wenn nicht, dann gibt es keinen Zyklus, egal wie tief die Verschachtelung ist. – danh
@danh: Der Zyklus ist nicht das Problem. Selbst am Leben zu bleiben, wenn es nicht gebraucht wird, ist das Problem. – gnasher729