- (void)didReceiveMemoryWarning - Verständnisproblem

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

  • - (void)didReceiveMemoryWarning - Verständnisproblem

    Hallo zusammen,

    ich habe mal wieder ein Verständnisproblem. In einem Tableview stelle ich Texte und Bilder dar, die ich aus einer SQLDatenbank übernehme.
    Das klappt auch wunderbar. Ab ca. 5.300 Datensätzen wird das Ram auf meinem iPod knapp und die APP stürzt ab.
    Mit Instruments kann ich den ansteigenden Speicherverbrauch beobachten bei ca. 185 Mb ist dann Schluss.

    Der Absturz ist ja erklärlich, für mich stellen sich trotzdem ein paar Fragen:
    - Hätte nicht vorher die Funktion - (void)didReceiveMemoryWarning aufgerufen werden müssen?
    - Warum erscheint keinerlei Fehlermeldung wie - out of memory - im Log?
    - Warum bleibt der Debugger nicht stehen?
    - Wie kann ich den freien Speicher abfragen um bereits vorher auf dem Speichermangel zu reagieren (z. B. Darstellung ohne Bild)?
    - Hat das iPhone 4 mehr Ram wie ein iPod (Kaufdatum 2011)? Das iPhone stürzt nicht ab und zeigt die ca. 6.000 Datensätze korrekt an.

    In der Console habe ich folgende Meldung:

    Quellcode

    1. Nov 17 08:27:45 unknown MobileITInventory[639] <Warning>: Item 5342 hinzugefuegt.
    2. Nov 17 08:27:46 unknown MobileITInventory[639] <Warning>: Item 5343 hinzugefuegt.
    3. Nov 17 08:27:46 unknown MobileITInventory[639] <Warning>: Item 5344 hinzugefuegt.
    4. Nov 17 08:27:46 unknown com.apple.launchd[1] <Notice>: (UIKitApplication:de.reiff.mobileITinventory[0xe809]) Bug: launchd_core_logic.c:3795 (24506):0
    5. Nov 17 08:27:46 unknown configd[25] <Notice>: jetsam: kernel termination snapshot being created
    6. Nov 17 08:27:46 unknown com.apple.debugserver-50[638] <Warning>: 1 [027e/1503]: error: ::read ( 4, 0x2ff7c9f0, 1024 ) => -1 err = Bad file descriptor (0x00000009)
    7. Nov 17 08:27:46 unknown lockdownd[17] <Error>: 011ad000 handle_connection: Could not receive USB message #41 from iTunes. Killing connection
    8. Nov 17 08:27:46 unknown com.apple.launchd[1] <Notice>: (UIKitApplication:de.reiff.mobileITinventory[0xe809]) Bug: launchd_core_logic.c:3794 (24506):3
    9. Nov 17 08:27:46 unknown com.apple.launchd[1] <Notice>: (UIKitApplication:de.reiff.mobileITinventory[0xe809]) Bug: launchd_core_logic.c:3202 (24506):10
    10. Nov 17 08:27:46 unknown com.apple.launchd[1] <Notice>: (UIKitApplication:de.reiff.mobileITinventory[0xe809]) Working around 5020256. Assuming the job crashed.
    11. Nov 17 08:27:46 unknown com.apple.launchd[1] <Warning>: (UIKitApplication:de.reiff.mobileITinventory[0xe809]) Job appears to have crashed: Segmentation fault: 11
    12. Nov 17 08:27:46 unknown com.apple.mobile.lockdown[17] <Notice>: Could not receive size of message
    13. Nov 17 08:27:46 unknown SpringBoard[27] <Warning>: Application 'MobileITInventory' exited abnormally with signal 11: Segmentation fault: 11
    14. Nov 17 08:27:47 unknown com.apple.mobile.lockdown[17] <Notice>: Could not receive size of message
    15. Nov 17 08:27:47 unknown lockdownd[17] <Error>: 011ad000 handle_connection: Could not receive USB message #6 from AppleMobileDeviceHelper. Killing connection
    16. Nov 17 08:27:47 unknown ReportCrash[693] <Error>: libMobileGestalt loadBasebandMobileEquipmentInfo: CommCenter error: 1:45
    17. Nov 17 08:27:47 unknown ReportCrash[693] <Error>: libMobileGestalt copyInternationalMobileEquipmentIdentity: Could not get mobile equipment info dictionary
    18. Nov 17 08:27:47 unknown ReportCrash[693] <Error>: Saved crashreport to /Library/Logs/CrashReporter/LowMemory-2011-11-17-082747.plist using uid: 0 gid: 0, synthetic_euid: 0 egid: 0
    19. Nov 17 08:27:47 unknown lockdownd[17] <Error>: 011ad000 handle_connection: Could not receive USB message #5 from AppleMobileDeviceHelper. Killing connection
    20. Nov 17 08:27:47 unknown com.apple.mobile.lockdown[17] <Notice>: Could not receive size of message
    21. Nov 17 08:27:48 unknown lockdownd[17] <Error>: 011ad000 handle_connection: Could not receive USB message #5 from AppleMobileDeviceHelper. Killing connection
    22. Nov 17 08:27:48 unknown com.apple.mobile.lockdown[17] <Notice>: Could not receive size of message
    23. Nov 17 08:27:48 unknown lockdownd[17] <Error>: 00190000 handle_connection: Could not receive USB message #7 from iTunes. Killing connection
    24. Nov 17 08:27:48 unknown com.apple.mobile.lockdown[17] <Notice>: Could not receive size of message
    25. Nov 17 08:27:49 unknown lockdownd[17] <Error>: 00190000 handle_connection: Could not receive USB message #15 from iTunes. Killing connection
    26. Nov 17 08:27:49 unknown com.apple.mobile.lockdown[17] <Notice>: Could not receive size of message
    27. Nov 17 08:27:51 unknown lockdownd[17] <Error>: 00190000 handle_connection: Could not receive USB message #7 from mobile_fs_util. Killing connection
    Alles anzeigen


    Den Eintrag aus dem Devicelog spare ich mir hier, sonst ist der Text zu lang.

    Am liebsten würde ich bei der Initialisierung den freien Speicher abfragen und hochrechen, ob der Speicher reicht. Dann ggf. Darstellung ohne Bilder.
    Zweite Möglichkeit - die Funktion - (void)didReceiveMemoryWarning wird aufgerufen. Alles wieder freigegeben und dann neu auch Darstellung ohne Bilder.
    Nur das die App ohne irgendeinen Hinweis abstürzt ist nicht akzeptabel.

    Als Übergangslösung werde ich die Bilder höher komprimieren. Nur löst das mein grundsätzliches Problem nicht. Denn spätestens bei 10.000 Datensätzen
    habe ich wieder kein Ram.

    Ich hoffe jemand hat einen Tipp für mich.

    Gruß Berthold
  • Wie wärs wenn du nicht alle Datensätz lädst sondern immer nur die die du auch brauchst +- ein paar fürs Cachen beim Scrollen ? Mal ganz davon abgesehen... Wer scrollt durch eine Tableview mit 10000 Einträgen ???? Irgendwie solltest Du einfach dein ganzes Konzept neu machen.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Wie soll das gehen mit dem cachen? Im Moment lade ich alle Daten aus der Datenbank in ein Array, welches dann als Datenquelle für den Tableview dient.
    Ich könnte dann statt der ganzen Datensätze nur die Indexe laden und im - (UITableViewCell*) tableView: (UITableView*)tView cellForRowAtIndexPath: (NSIndexPath*)indexPath
    die eigentlichen Daten nachladen. Ich werde das in jedem Fall in den nächsten Tagen mal ausprobieren.
    Aber ist das nicht viel zu langsam, wenn ich für jedes Bild die Datenbank einzeln abfragen muss? Und was passiert, im unwahrscheinlichen Fall das jemand wirklich die 6.000 Datensätze durchscrollt? Dann lande ich doch wieder beim gleichen Problem, oder etwa nicht?

    Claus hat natürlich Recht wenn er sagt, dass normalerweise niemand tausende von Datensätzen durchscrollt. Im Normalfall kommt daher eine gefilterte Ausgabe mit durchschnittlich 20 Einträgen zum Einsatz. Aber ich denke es ist auch kein guter Stil wenn man dem Anwender die Möglichkeit nimmt alle Daten auf einmal zu sehen. Wie bereits gesagt ist es für diesen Sonderfall auch kein Problem auf die Bilder zu verzichten, wenn ich nur erkennen kann das der Speicher knapp wird.

    Gruß Berthold
  • Die Tableview sorgt doch schon selber dafür, dass immer nur die Zellen geladen werden die gebraucht werden. Wenn Du nun diese Zellen immer mit ensprechenden Content versorgst, diesen Content dir aber nciht selber merkst sondern der Tableview überläßt zu entscheiden was sie beahlten will und was nicht dann ist der erste richtige Schritt getan.
    Wie Du aber schon sagst kann es sein, das das Laden aus der Datenbank in cellForRow zu langsam ist. Aber das gilt es ja erst einmal herauszufinden. Wenn das wirklich so ist, dann must du halt asynchron laden. Aber erst einmal so probieren, denn nichts ist schlimmer als etwas unnötig zu optimieren. Das macht den Code immer schwerer lesbar.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Nochmals vielen Dank für den Tipp. Ich habe es entsprechend eingebaut und es klappt alles bestens.
    Der Speicherverbrauch ist wie zu erwarten dramatisch zurückgegangen.
    Man merkt zwar, dass das Scrollen etwas langsamer geht als wenn ich die Daten vorher lade.
    Es ist aber in jedem Fall noch ausreichend schnell.

    Trotzdem verstehe ich nicht warum in meiner Ursprungsversion vor dem Absturz nicht die Funktion
    - (void)didReceiveMemoryWarning aufgerufen wurde.

    Gruß Berthold