2013-04-02 3 views
6

Ich habe eine Auto-synthetisierte readonly & weak Eigenschaft:Prevent ARC zu null einer schwachen Ivar direkt nach Zuweisung (in Version baut)

@property (nonatomic, readonly, weak) KTWindowController* windowController; 

I die synthetisierte Ivar zuweisen und dann auf ein Array hinzuzufügen:

_windowController = [KTWindowController controller]; 
[self addSubController:_windowController]; 

Dies funktioniert in Debug-Builds. Aber ich habe einen Bericht erhalten, der bei der Veröffentlichung (ad hoc) sofort die _windowController erstellt und dann versucht, nil zu dem Array hinzuzufügen, was die App zum Absturz bringt.

Welche spezifische Einstellung (Optimierungsstufe?) In einem Release-Build (Ad-hoc-Build) ändert dieses Verhalten im Vergleich zu Debug-Builds?

Es scheint mir seltsam, dass dieses Verhalten von Debug zu Release Builds ändern würde. Aber ich konnte dieses Verhalten reproduzieren, und es macht tatsächlich Sinn - nur nicht, wenn es nicht mit dem übereinstimmt, was in Debug-Builds passiert.

Die vorgeschlagene Abhilfe:

KTWindowController* windowController = [KTWindowController controller]; 
[self addSubController:windowController]; 
_windowController = windowController; 

Andere als eine lokale Variable, wie oben zu sehen ist, was Abhilfe würden Sie in solchen Fällen empfehlen?

+0

Vielleicht ist das eine dumme Frage, aber warum weisen Sie direkt dem ivar zu, anstatt 'self.windowController = [KTWindowController controller]' 'zu verwenden? – bdesham

+0

Die Frage ** ist ** albern: Die Eigenschaft ist readonly. ;) – LearnCocos2D

+1

OK, fair genug ;-) – bdesham

Antwort

1

Wenn Sie eine Eigenschaft als schwach erklären, Sie sind viel versprechend, dass einige ein anderes Objekt kümmert sich um das Eigentum. Das ist, was schwach bedeutet. Wenn Sie dies verletzen, passieren schlimme Dinge. So zum Beispiel, wenn Sie schreiben:

KTWindowController* windowController = [KTWindowController controller]; 
[self addSubController:windowController]; 
_windowController = windowController; 

Sie treffen Ihre Verpflichtungen: die starke temporäre Variable windowController Griffe Eigentum innerhalb dieser Methode, und dann behandelt windowController subController Eigentum danach.

Wenn Sie schrieb

_windowController = [KTWindowController controller]; 

Sie nicht taten, was Sie zu tun versprochen. _windowController ist schwach, also verwaltet jemand anderes die Lebensdauer. Aber schau! Niemand verwaltet das Leben! Wir sind also frei, die schwache Variable loszuwerden, wann immer wir wollen. Der Optimierer sieht dies in Ihrer Version an und sagt:

Hey! Dieser Typ sagt, dass es ihm egal ist, ob dieser Fenstercontroller lebt oder stirbt, solange sich niemand sonst darum kümmert. Einige Leute! Aber das geht mich nichts an. Aber sieh dir das an: da es ihm egal ist, muss ich es gar nicht machen! Jedenfalls kann ich es sofort loswerden, wenn ich es mache.

Der Compiler macht nur das, was Sie sagten, dass Sie wollten.

Sind Sie sicher, dass Sie möchten, dass dies eine schwache Eigenschaft ist? Immer wenn ich das in meinem Code sehe, achte ich darauf, dass die Eigenschaft wirklich schwach ist. oft möchte ich sowieso eine starke Eigenschaft.

0

Ich fand heraus, dass die Änderung der Optimierungsstufe von None (-O0) zu Fast (-O, O1) dieses Problem einführt.

As mentioned here, dieses Verhalten ist zu erwarten. Es sollte wirklich eine Compiler-Warnung sein.

landete ich die zusätzliche Zeile in der Umgehungs Verschmelzung durch die Zuordnungen zu einer Linie bewegen, dies funktioniert genauso gut:

// extra local var to prevent ARC from nil'ing the weak var right away in release 
KTWindowController* windowController = _windowController = 
               [KTWindowController controller]; 
[self addSubController:windowController]; 
+0

Also was ist der Zweck der Immobilie, wenn sie unbrauchbar ist? –

+1

Es sollte keine Compiler-Warnung sein, Sie sagen, dass Sie ein Objekt zuweisen möchten, ohne die Retain-Anzahl zu erhöhen, weil Sie es nur brauchen, während es woanders verwendet wird, und das ist eine perfekte Aussage, Sie müssen es nur wissen von dem, was du tust. Was Sie tun, ist es auf eine starke Variable verweisen, so dass es beibehalten wird, bis diese Variable entsorgt wird. –

+0

@HotLicks Ich stimme zu, es wäre einfacher, eine "readwrite strong" -Eigenschaft zu verwenden, aber vielleicht braucht er es wirklich, um so zu sein. –

Verwandte Themen