2013-04-17 10 views
10

jedes Mal, wenn ich in einem Block wie diese eine globale var oder Eigentum verwenden:die Vermeidung der „Erfassung selbst stark in diesem Block wird wahrscheinlich zu einem behalten Zyklus führen“ Nachricht

self.save = ^(){ 
    if (isItSaving == NO) { 
     [self saveMyFile]; 
    } 
}; 

ich neu zu schreiben dies wie

BOOL *iis = isItSaving; 
id myself = self; 

self.save = ^(){ 
    if (iis == NO) { 
     [myself saveMyFile]; 
    } 
}; 

oder Xcode wird sich beschweren, „selbst stark in diesem Block die Erfassung wird wahrscheinlich zu einem behalten Zyklus führen ...

Es beschwert sich sogar über BOOL Variablen?

Alles neu deklarieren, bevor ein Block erscheint, ist eine lahme Lösung.

Ist das der richtige Weg? Gibt es einen eleganten Weg?

Dieses Zeug ist hässlich. Ich benutze ARC.

Antwort

20

Das Problem tritt nur auf, wenn explizit oder implizit aus dem Block auf self verwiesen wird. Beim Zugriff auf globale Variablen wird keine Warnung ausgegeben.

In Ihrem Fall haben Sie wahrscheinlich auf einen (booleschen) ivar zugegriffen. Der Zugriff auf das ivar verwendet implizit self, deshalb warnt der Compiler Sie (korrekt) über einen Retain-Zyklus.

Der gemeinsame Weg, um den Zyklus beibehalten zu beheben ist:

typeof(self) __weak weakSelf = self; 

self.save = ^() { 
    typeof(weakSelf) __strong strongSelf = weakSelf; 
    if (strongSelf != nil && ! strongSelf->isItSaving) { 
     [strongSelf saveMyFile]; 
    } 
}; 

... und, ja, das ist ein bisschen ein hässliches Teil der Blöcke.

+1

Mann, das ist hässlich wie die Hölle. Alles neu deklarieren zu müssen ... danke. – SpaceDog

+0

@MarkAmery Ja, Clang fängt immer mehr an. Und es ist richtig, die Lebensdauer des einschließenden Objekts sollte mindestens bis zum Ende des Blocks verlängert werden. Editing ... –

+1

@NikolaiRuhe * "die Lebensdauer des einschließenden Objekts sollte mindestens bis zum Ende des Blocks verlängert werden" * - nett, habe ich zunächst keinen Grund bemerkt, warum ich einen starken Bezug auf 'self' innerhalb des Blocks habe wäre besser als "__unsafe_unreteted", aber dieser Satz allein macht es unglaublich klar. Es könnte sich sogar lohnen, die beiden Ansätze in Ihrer Antwort zu vergleichen, wenn Sie es wünschen. –

4

Verwenden __unsafe_unretained typeof(self) weakSelf = self;

+0

Ich denke, dass Sie __unsafe_unrealted mit ARC nicht verwenden können – SpaceDog

0

Neben @ NikolaiRuhe Antwort, in Ihrem Beispiel, wenn die Eigenschaften erklären

BOOL *iis = isItSaving; 
id myself = self; 

impliziert strong Referenzen, so __weak selbst verwenden, um den Zyklus beibehalten zu verhindern. Dann könnten Sie sich fragen, warum Sie einen Verweis auf schwaches Selbst innerhalb des Blocks deklarieren müssen, und das ist, um sicherzustellen, dass es während der Lebensdauer des Blocks nicht freigegeben wird, andernfalls weakSelf->isItSaving würde brechen, wenn self freigegeben wurde.

Verwandte Themen