Brauche Hilfe - Memory Management von xib und images

  • Brauche Hilfe - Memory Management von xib und images

    hallo zusammen,

    ich bin noch neu in der IPhonde Entwicklung und habe einige Problem und hoffe das ihr mir weiterhelfen könnt....

    Folgendes Problem, ich öffne viele xib's mit entsprechenden ViewControllern. In diesen xib's habe ich viele Bilder lediglich per Interface Bulilder eingebunden.
    da ich die views wechsel (s. Code 1), werden die Bilder nicht mehr benötigt! wie kann ich diese Bilder richtig entladen? sodass wieder RAM freigegeben wird und ich nicht so schnell eine MemoryWarning erhalte.

    CODE 1

    Quellcode

    1. View01 *myFirstView = [[View01 alloc] initWithNibName:nil bundle:nil];
    2. myFirstView.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    3. [self presentModalViewController: myFirstView animated:YES];
    4. [myFirstView release];



    Zweite Frage:
    Momentan friert die App ein paar sekunden ein, sobald ich eine MemoryWarning erhalte. Bitte korrigiert mich wenn ich falsch liege, ich denke das es daran liegt das dann sehr viel RAM auf einmal freigegeben wird - RICHTIG ?
    Wenn alles richtig gemacht wurde - dürfte es doch nicht zu so einem Einfrieren kommen oder?

    Bitte um Hilfe und bedanke mich schonmal im Vorraus!
    greetz runkelrübe43
  • Hm ich verstehe gerade nicht wie man es schafft so viele Bilder im Speicher zu halten, dass man Memory warnings bekommt. Mehr als das Display groß ist kann man ja eh nicht anzeigen. Also warum nimmst Du nicht einfach 1 View (oder meinetwegen auch so viele wie wie Du gleichzieitig sehen kannst) und veränderst die Inhalte wenn es nötig wird ?

    Ich glaube Dein Problem steckt im Konzept und nicht in der Programmierung.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • runkelrübe43 schrieb:

    wie kann ich diese Bilder richtig entladen?
    Wenn Du sie über die NIB-Datei lädst, werden sie gecacht und dieser Cache wird vom iOS verwaltet. Da hast Du keinen Zugriff drauf.

    runkelrübe43 schrieb:

    Bitte korrigiert mich wenn ich falsch liege, ich denke das es daran liegt das dann sehr viel RAM auf einmal freigegeben wird - RICHTIG ?
    Wahrscheinlich ist nicht die absolute Größe des Speichers sondern die Anzahl der Blöcke entscheidend. Aber vielleicht solltest Du mal schauen, was bei einer Speicherwarnung so alles in Deinem Code passiert.

    runkelrübe43 schrieb:

    Wenn alles richtig gemacht wurde - dürfte es doch nicht zu so einem Einfrieren kommen oder?
    Das erinnert mich an den Spruch eines Kollegen: Kaum machst Du es richtig, schon funktioniert es.

    In der katholischen Kirche erhältst Du nur dann die Absolution, wenn Du alles beichtest und aufrichtig bereust. So weit bist Du noch nicht.
    „Meine Komplikation hatte eine Komplikation.“
  • Das sind zwei Fragen ;)

    iOS cached alle Bilder, die über imageNamed: geladen werden. Wenn Du die Bilder über eine andere Methode erzeugst, werden sie nicht gecached: developer.apple.com/library/io…c/uid/TP40006890-CH3-SW11
    Cocoa Touch gibt einen geladenen View nur bei Speicherproblemen frei. Er bleibt also nach der Anzeige bis zur nächsten Speicherwarnung oder der Zerstörung des View-Controllers im Speicher. Um diesen Punkt brauchst Du Dir also keine Gedanken zu machen.
    „Meine Komplikation hatte eine Komplikation.“
  • Danke dir!

    Wie würdest du das Problem lösen?
    "Du hast viele Views (xib's) mit entsprechenden View Controllern die nach und nach aufgerufen werden (wie level in einem Spiel). In den Xib's wurden Bilder angelegt die nicht mit outlets verknüpft wurden (wie einfache hintergrundsbilder), jedoch werden dies nicht mehr gebraucht, sobald man den view verlässt. Somit sollten diese den Ram nicht weiterhin zukleistern."


    Hast du eine Idee?

    greetz
  • Die Bilder kannst Du ja per Code und nicht per Interface Builder laden. Wenn es viele Bilder sind geht das vielleicht auch sowieso einfacher und bequemer über eine Schleife. Außerdem solltest Du prüfen, ob Du nicht nur die Bilder laden kannst, die auch tatsächlich angezeigt werden.

    Um den View brauchst Du Dich meines Erachtens überhaupt nicht zu kümmern. Der wird ja sowieso rausgeschmissen, wenn das iOS ihn nicht mehr braucht.
    „Meine Komplikation hatte eine Komplikation.“
  • hi,

    ich habe jetzt nochmal diese Methode ausprobiert:

    Quellcode

    1. UIImage *myImagebg=[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"0" ofType:@"jpg"]];
    2. [bg setImage:myImagebg];
    3. [myImagebg release];

    Wenn ich jedoch mit Instruments mir dem MemoryMonitor anschaue wird der freie Speicher immer kleiner.

    evtl. habe ich ein generelles Verständnis Problem!?
    wenn ich alles richtig released und auf nil gesetzt habe, sollte der Speicher bei einer MemoryWarning geleert werden ohne das ein Einfrieren stattfindet? oder sollte es dann normaler weise nie zu einer MemoryWarning kommen?


    nochmal VIELEN DANK für deine schnelle und kompetente Hilfe ^^
  • So als Tipp:

    Man darf nur releasen was man alloziert hat.

    Jetzt schaumal:

    imageWithContentsOfFile

    ist eine Klassenmethode. Das Image das Du dort bekommst wird also von der Klasse alloziert und mit autorelease an Dich weitergegeben. Also hast Du die nicht nochmal freizugeben, es sei denn Du würdest sie einer Variablen zuweisen, die mit retain deklariert ist.

    Was Du willst ist ein

    Quellcode

    1. UIImage *image=[UIImage alloc] initWithContentOfFile:..... ]];
    2. .
    3. .
    4. .
    5. [image release];


    Aber ich denke am besten ist es Du versuchst erstmal eine einfacherer App zu schreiben um zu verstehen wie das Memory-Management überhaupt funktioniert.
    So wie Du es jetzt machst wird es zwangsläufig zu einer App führen, die entweder Speicher frisst wie blöde, oder abstürzt weil sie falschen Speicher frei gibt.

    Nicht für ungut, wir mussten da alle mal durch und da hilft nur lesen, ausprobieren (immer schön mit Leaktool arbeiten) und nochmal lesen und wieder ausprobieren und irgendwann versteht man es dann.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • das bild wird nicht aus dem speicher geblasen nur weil du release machst. es wird auch nicht geladen nur weil du alloc oder init machst.
    das bild wird erst in den speicher geladen sobald die daten wirklich gebraucht werden (zb beim zeichnen) dann aber wohl nicht mehr freigegeben bis zum dealloc.
    dealloziert wird natürlich erst wenn in deinem fall auch das imageview dealloziert wird oder du ein anderes image setzt etc...
  • macmoonshine schrieb:

    Wieso sollte er das umschreiben? Er braucht doch einfach nur die Zeile mit dem release rausschmeißen, wie gritsch schon angemerkt hat.

    developer.apple.com/library/io…ef/doc/uid/TP40004447-SW1


    Es ging aber doch darum das er selber die Images rauswerfen will wenn er sie nicht mehr braucht und das ist beim autorelease ja nicht unbedingt der Fall. Deshalb dachte ich er will explizit den release machen können.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Thallius schrieb:

    macmoonshine schrieb:

    Wieso sollte er das umschreiben? Er braucht doch einfach nur die Zeile mit dem release rausschmeißen, wie gritsch schon angemerkt hat.

    developer.apple.com/library/io…ef/doc/uid/TP40004447-SW1


    Es ging aber doch darum das er selber die Images rauswerfen will wenn er sie nicht mehr braucht und das ist beim autorelease ja nicht unbedingt der Fall. Deshalb dachte ich er will explizit den release machen können.

    Gruß

    Claus


    ist auch beim manuellen release nicht der fall wie ich grad beschreiben habe
  • gritsch schrieb:


    das bild wird erst in den speicher geladen sobald die daten wirklich gebraucht werden (zb beim zeichnen) dann aber wohl nicht mehr freigegeben bis zum dealloc.


    Das kann ich mir jetzt aber mal so gar nicht vorstellen. Wie sollte man denn dann bitte ein Pre-Caching implementieren ?

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • gritsch schrieb:

    Thallius schrieb:

    macmoonshine schrieb:

    Wieso sollte er das umschreiben? Er braucht doch einfach nur die Zeile mit dem release rausschmeißen, wie gritsch schon angemerkt hat.

    developer.apple.com/library/io…ef/doc/uid/TP40004447-SW1


    Es ging aber doch darum das er selber die Images rauswerfen will wenn er sie nicht mehr braucht und das ist beim autorelease ja nicht unbedingt der Fall. Deshalb dachte ich er will explizit den release machen können.

    Gruß

    Claus


    ist auch beim manuellen release nicht der fall wie ich grad beschreiben habe


    Jein,

    klar wird der Speicher nicht direkt freigegeben, aber ich selber habe zumindest alles getan um dem System diesen Speicher wieder zur Verfügung zu stellen.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Thallius schrieb:

    gritsch schrieb:

    Thallius schrieb:

    macmoonshine schrieb:

    Wieso sollte er das umschreiben? Er braucht doch einfach nur die Zeile mit dem release rausschmeißen, wie gritsch schon angemerkt hat.

    developer.apple.com/library/io…ef/doc/uid/TP40004447-SW1


    Es ging aber doch darum das er selber die Images rauswerfen will wenn er sie nicht mehr braucht und das ist beim autorelease ja nicht unbedingt der Fall. Deshalb dachte ich er will explizit den release machen können.

    Gruß

    Claus


    ist auch beim manuellen release nicht der fall wie ich grad beschreiben habe


    Jein,

    klar wird der Speicher nicht direkt freigegeben, aber ich selber habe zumindest alles getan um dem System diesen Speicher wieder zur Verfügung zu stellen.

    Gruß

    Claus


    sonst machts das system halt selbst (und das nicht viel später)
  • Abgesehen davon erfolgt im Allgemeinen die Freigabe des Autorelease-Pools nur im Millisekunden-Bereich später als ein release. Falls das mal nicht der Fall sein sollte, hast Du zumindest in iOS eine sehr problematische Stelle, die wahrscheinlich noch mehr Ärger machen wird.
    „Meine Komplikation hatte eine Komplikation.“