UIViewController Verhalten

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • UIViewController Verhalten

    Hallo zusammen,

    Ich lasse einen UIViewController (der UIView davon zumindest) mittels

    Quellcode

    1. presentModalViewController:controller animated:YES
    einblenden. Ich kann jedoch nicht feststellen, dass der UIViewController wieder gelöscht (released) wird. Nun stellt sich die Frage, ob ich da ein massives Memory Leak baue? Im Profiler kann ich nur sehen, das mein App schnell 30 MB braucht, wenn ich den oben angegebenen UIViewController mehrmals nacheinander einblenden lasse. Der UIView ist jedoch ziemlich aufwändig, braucht aber sicher nicht 30 MB ;).

    Kann mir jemand dieses Verhalten erklären? Wieso wird der UIViewController nicht gelöscht?
  • Klar,

    Quellcode

    1. NewPostViewController* controller = [[NewPostViewController alloc] initWithNibName:@"NewPostViewController" bundle:nil];
    2. [self presentModalViewController:controller animated:YES];
    3. [controller release];
  • Entscheidend ist die Frage, ob bei jeder Anzeige des View-Controllers der Speicherverbrauch steigt und somit der Gesamtverbrauch immer höher wird. Das iOS merkt sich beispielsweise die Bilder der Views im Hauptspeicher. Das kann schon einige MB ausmachen. Gibst Du im View-Controller auch immer schön brav alle Outlets frei?

    Wenn das Alles nicht hilft, solltest Du mal Instruments mit Leaks drüber laufen lassen.
    „Meine Komplikation hatte eine Komplikation.“
  • macmoonshine schrieb:

    Entscheidend ist die Frage, ob bei jeder Anzeige des View-Controllers der Speicherverbrauch steigt und somit der Gesamtverbrauch immer höher wird. Das iOS merkt sich beispielsweise die Bilder der Views im Hauptspeicher. Das kann schon einige MB ausmachen. Gibst Du im View-Controller auch immer schön brav alle Outlets frei?

    Wenn das Alles nicht hilft, solltest Du mal Instruments mit Leaks drüber laufen lassen.
    Da ich keine Referenzen dazu mache, brauche ich die ja auch nicht frei zu geben?
    Doch, jedes mal, wenn ich den UIView anzeigen lasse, braucht es mehr Speicher, was ich etwas eigenartig finde, da der UIView haufenweise Bilder enthält.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von junky94 ()

  • In dealloc und viewDidUnload. Das gilt auch für Outlets, die Du nicht als Property sondern nur als Attribut deklariert hast. Die müssen in beiden Methoden ein release und in viewDidUnload auch noch auf nil gesetzt werden. Am besten verwaltest Du sie natürlich über Setter.
    „Meine Komplikation hatte eine Komplikation.“
  • macmoonshine schrieb:

    In dealloc und viewDidUnload. Das gilt auch für Outlets, die Du nicht als Property sondern nur als Attribut deklariert hast. Die müssen in beiden Methoden ein release und in viewDidUnload auch noch auf nil gesetzt werden. Am besten verwaltest Du sie natürlich über Setter.
    Wieso muss man das machen? Die Klasse hat ja keine richtige Referenz zum Outlet und wird ja dann so oder so gelöscht, wenn der UIView weg ist.
  • Der UIViewController wird gar nicht dealloziert. Ich hab einen NSLog Aufruf in dealloc gesetzt. Nichts wird in der Konsole ausgegeben. Das kann ja nicht der Normalfall sein?
  • junky94 schrieb:

    macmoonshine schrieb:

    In dealloc und viewDidUnload. Das gilt auch für Outlets, die Du nicht als Property sondern nur als Attribut deklariert hast. Die müssen in beiden Methoden ein release und in viewDidUnload auch noch auf nil gesetzt werden. Am besten verwaltest Du sie natürlich über Setter.
    Wieso muss man das machen? Die Klasse hat ja keine richtige Referenz zum Outlet und wird ja dann so oder so gelöscht, wenn der UIView weg ist.

    Apple hält sich an dieser Stelle leider bewusst nicht an seine eigenen Speicherverwaltungsregeln: developer.apple.com/library/io…ef/doc/uid/TP40004998-SW4. Glücklicherweise erzeugt Xcode 4 dafür aber den richtigen Speicherverwaltungscode.
    „Meine Komplikation hatte eine Komplikation.“
  • junky94 schrieb:

    Der UIViewController wird gar nicht dealloziert. Ich hab einen NSLog Aufruf in dealloc gesetzt. Nichts wird in der Konsole ausgegeben. Das kann ja nicht der Normalfall sein?

    Die Erzeugung des View-Controllers sieht richtig aus. Das heißt aber nicht, dass da nicht irgendwo ein anderer Speicherverwaltungsfehler in Deinem Code ist. Schickst Du irgendwo sonst noch ein retain oder weist Du ihn einer retained Property zu?
    „Meine Komplikation hatte eine Komplikation.“
  • macmoonshine schrieb:

    junky94 schrieb:

    Der UIViewController wird gar nicht dealloziert. Ich hab einen NSLog Aufruf in dealloc gesetzt. Nichts wird in der Konsole ausgegeben. Das kann ja nicht der Normalfall sein?

    Die Erzeugung des View-Controllers sieht richtig aus. Das heißt aber nicht, dass da nicht irgendwo ein anderer Speicherverwaltungsfehler in Deinem Code ist. Schickst Du irgendwo sonst noch ein retain oder weist Du ihn einer retained Property zu?
    Ja, hab ich auch gerade festgestellt. Der retainCount bleibt nach dem Ausblenden auf 3, obwohl sonst keine Klasse überhaupt diesen UIViewController kennt?
  • macmoonshine schrieb:

    In dealloc und viewDidUnload. Das gilt auch für Outlets, die Du nicht als Property sondern nur als Attribut deklariert hast.

    Bist Du Dir da sicher? Ich würde das eher mit einem „kommt drauf an“ beantworten. Ich mein, wenn ich zum Beispiel ein IBOutlet nur als Attribut deklariert habe, welches mit einem UITextField in der View Hierachie verbunden ist, würde ich das lieber nicht releasen.

    Michael
  • junky94 schrieb:

    Kannst du mir nochmals ganz kurz erklären, wieso Outlets in dealloc released werden müssen? Amin macht das in seinem Buch auch nie und es erzeugt ja auch keine Leaks?

    Amin's Buch behandelt erstens Mac OS X, wo das mit den Top-Level-Objekten in Nib-Files anders läuft, als unter iOS und zweitens glaube ich nicht, dass er das in seinem Buch nie macht.

    Michael
  • Michael schrieb:

    macmoonshine schrieb:

    In dealloc und viewDidUnload. Das gilt auch für Outlets, die Du nicht als Property sondern nur als Attribut deklariert hast.

    Bist Du Dir da sicher? Ich würde das eher mit einem „kommt drauf an“ beantworten. Ich mein, wenn ich zum Beispiel ein IBOutlet nur als Attribut deklariert habe, welches mit einem UITextField in der View Hierachie verbunden ist, würde ich das lieber nicht releasen.

    Dann hast Du ein Leak. Wie bereits geschrieben hält sich Apple hier nicht an seine eigenen Speicherverwaltungsregeln. Den Link dazu habe ich auch schon gepostet.

    Außerdem macht es Xcode 4 beim Anlegen eines Outlet-Attributs auch so. Es erzeugt Dir ein

    Quellcode

    1. [myOutlet release];
    2. myOutlet = nil;
    „Meine Komplikation hatte eine Komplikation.“