2011-01-14 16 views
2

Nach 3 Stunden oder so, habe ich es endlich geschafft, ein Speicherleck in einem View-Controller zu beheben. Das Leck wurde von einem UIPickerView verursacht, dessen Eigenschaft in der Headerdatei auf "beibehalten" gesetzt ist.Objective-C Speicherverwaltung - ziemlich sicher mache ich das alles falsch

Der folgende Code verwaltet, es zu beheben:

- (void)viewDidLoad { 
    [super viewDidLoad];  
    myPicker = [[[UIPickerView alloc] initWithFrame:CGRectZero]autorelease]; 
} 

- (void)dealloc { 
    [super dealloc]; 
    [myPicker release]; 
    myPicker = nil; 
} 

Bitte sagen Sie mir nicht, wie schockierend dieser Code ist ... Ich weiß, dass es schlecht ist. Ich habe eine Freigabe, und eine Autorelease. Problem ist, wenn ich einen Teil des Obigen ändere oder entferne, kommt das Gedächtnisleck zurück.

ich aber wusste ich, wie Objective-C-Speicherverwaltung funktioniert, natürlich nicht ...

Warum der obige Code den Speicherverlust zu beheben, und was könnte eine korrekte Version des Codes aussehen?

-

EDIT:

Wenn jemand das gleiche Problem hat, oder interessiert - das Problem war, dass eines der anderen Objekte in meiner Klasse wurde auf ‚behalten‘ und nicht ‚zuweisen ". (Wenn Sie kein Objekt besitzen, sollte die Eigenschaft zugewiesen, nicht beibehalten werden).

Wie Cannondale sagte, behebt das Entfernen der zusätzlichen Behalten alles, und nur eine Version ist notwendig.

+0

Freut mich zu hören, dass Sie es aussortiert haben. Nice one :) – RedBlueThing

+0

das kann helfen: http://interfacelab.com/objective-c-memory-management-for-lazy-people/ – hlfcoding

Antwort

4

Sie müssen einen myPicker an anderer Stelle in Ihrem Code aufbewahren. Ihre myPicker-Zuweisungszeile wird diesen Speicher freigeben, sobald sich der Stapel für den viewDidLoad-Aufruf aufrollt (das ist es, was die Autorelease ihm sagt).

Sie müssen irgendwo nach diesem Punkt ein Retain machen, wenn nicht, dann wird Ihre [myPicker-Version] versuchen, nicht zugewiesenen Speicher mit unvorhersehbaren Ergebnissen freizugeben.

Was Sie tun sollten, ist die Zuweisung des Speichers in viewDidLoad (so entfernen Sie die Autorelease). Stellen Sie sicher, dass Sie das Objekt nirgendwo anders behalten und myPicker vom Dealloc freigeben.

Auch ... was bbum re der dealloc sagte;)

+0

Danke - macht sehr viel Sinn! Sehr geschätzt :) Jetzt, nur um den zusätzlichen zu finden, behalten Sie ... –

+0

Ist 'myPicker' eine Eigenschaft, die Sie in Ihrer Schnittstellendatei erstellt haben, eine, die Sie" behalten ", vielleicht? Das ist meine Vermutung. –

4

Was sagte Cannonade. Dies sollte funktionieren:

myPicker = [[UIPickerView alloc] initWithFrame:CGRectZero]; 

Ihre dealloc gesprengt wird, auch. Call to super muss immer der letzte sein (darüber nachdenken) und das kann zu undefiniertem Verhalten führen.

- (void)dealloc { 
    [myPicker release]; 
    myPicker = nil; 
    [super dealloc]; 
} 
+0

Das ist immer noch sehr elegant. Ich denke, es ist Zeit, ObjC für mich zu lernen. –

+0

Kein Grund, myPicker hier auf Null zu setzen. Dies ist das letzte Mal, dass Sie sich darauf beziehen können, so dass es nicht die Gefahr gibt, es versehentlich zu dereferenzieren. – JeremyP

+0

Wahr genug; Am Ende mache ich es aus Gewohnheit als '[foo release], foo = nil;'.Erleichtert das Debuggen hin und wieder (und ich kann Triple klicken Sie auf Kopieren/Einfügen, wenn ich außerhalb dealloc freigeben muss). – bbum