Release UINavigationController in ARC

  • Release UINavigationController in ARC

    Hallo Forum-Mitglieder,

    ich habe eine kurze Frage. Ich habe einen UINavigationscontroller und lade zusätzlich einen Navigationscontroller hinzu. Wenn ich jetzt vom 2 in den 1 Navigationcontroller zurück springe, ist laut Speicherverbrauchsanzeige
    in Xcode der Navigationscontroller immer noch im Speicher. Wie kann ich diesen in ARC releasen.

    So lade ich den zweiten Navigationscontroller:

    Quellcode

    1. FileViewer_Collection_ViewController* ViewerController = [self.storyboard instantiateViewControllerWithIdentifier:@"fileviewer_controller"];
    2. ViewerController.Pfad = [filename.filename_url path];
    3. ViewerController.title = filename.filename_str;
    4. [self.navigationController pushViewController:ViewerController animated:YES];


    Wäre über einen Tipp oder Rat sehr Dankbar!

    Gruss
    necromonger
  • necromonger schrieb:

    Wenn ich jetzt vom 2 in den 1 Navigationcontroller zurück springe, ist laut Speicherverbrauchsanzeige
    in Xcode der Navigationscontroller immer noch im Speicher. Wie kann ich diesen in ARC releasen.
    Woher weist du, dass das genau dein Viewcontroller ist? Hast du dir deine App mal mit Instruments angesehen?

    Du kannst in ARC kein Objekt explizit aus dem Speicher werfen. Dafür steht das A in ARC. ;)
    „Meine Komplikation hatte eine Komplikation.“
  • Hallo macmoonshine,

    ich gehe davon aus, dass der Navigationscontroller aus dem Speicher nicht mehr freigegeben wird. Mit Instruments habe ich es noch nicht versucht, ich muss ehrlich sagen
    ich blicke auch nicht ganz durch bei Instruments. Wenn ich vom 1 in den 2 Navigationscontroller springe erhöht sich immer weiter der verbrauchte Speicher im Arbeitsspeicher, um
    so öfter ich hin und her springe!

    Gruss
    necromonger
  • Delegates sind in der Regel auch schwache Referenzen. Daran sollte es auch nicht liegen.

    Das Notification-Center hält seine Observer nicht. Wenn ARC einen Observer wegräumt gibt es stattdessen einen Satz heißer Ohren. Außer du verwendest Code-Blöcke als Observer. Wenn die self enthlten, hast du schnell einen Retain-Cycle.
    „Meine Komplikation hatte eine Komplikation.“
  • Danke für deine Hilfe. Also Code-Blöcke enthalten die Observer nicht. Ich führe aber in dem UINavigationcontroller eine Dispatch_async aus.

    Quellcode

    1. dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    2. dispatch_async(dispatch_get_main_queue(), ^(void){
    3. UIAlertController *alertController = [UIAlertController
    4. alertControllerWithTitle:@"Erzeuge"
    5. message:nil
    6. preferredStyle:UIAlertControllerStyleActionSheet];
    7. UIAlertAction *cancelAction = [UIAlertAction
    8. actionWithTitle:NSLocalizedString(@"Abbrechen", @"Cancel action")
    9. style:UIAlertActionStyleCancel
    10. handler:^(UIAlertAction *action)
    11. {
    12. NSLog(@"Cancel action");
    13. }];
    14. UIAlertAction *okAction = [UIAlertAction
    15. actionWithTitle:NSLocalizedString(@"neuen Ordner", @"OK action")
    16. style:UIAlertActionStyleDefault
    17. handler:^(UIAlertAction *action)
    18. {
    19. [self createnewfolder_controller];
    20. }];
    21. [alertController addAction:cancelAction];
    22. [alertController addAction:okAction];
    23. alertController.popoverPresentationController.barButtonItem = _action_toolbar_add_button;
    24. alertController.popoverPresentationController.sourceView = self.view;
    25. [self presentViewController:alertController animated:YES completion:nil];
    26. });
    27. });
    Alles anzeigen


    Könnte das zu diesem Problem führen?
  • Kannst du den Code mal einrücken.

    Wie dem auch sei. Die ersten beiden Zeilen sind so schon mal wenig sinnvoll. Du kannst die erste und letzte Zeile getrost streichen.

    Die Code-Blöcke der Alert-Actions halten self solange, bis der Alert-Controller das Zeitliche segnet.
    „Meine Komplikation hatte eine Komplikation.“
  • Quellcode

    1. dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    2. dispatch_async(dispatch_get_main_queue(), ^(void){
    3. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Erzeuge" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    4. UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Abbrechen", @"Cancel action") style:UIAlertActionStyleCancel
    5. handler:^(UIAlertAction *action)
    6. {
    7. NSLog(@"Cancel action");
    8. }];
    9. UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"neuen Ordner", @"OK action") style:UIAlertActionStyleDefault
    10. handler:^(UIAlertAction *action)
    11. {
    12. [self createnewfolder_controller];
    13. }];
    14. [alertController addAction:cancelAction];
    15. [alertController addAction:okAction];
    16. alertController.popoverPresentationController.barButtonItem = _action_toolbar_add_button;
    17. alertController.popoverPresentationController.sourceView = self.view;
    18. [self presentViewController:alertController animated:YES completion:nil];
    19. });
    20. });
    Alles anzeigen
  • Ausgehend von dem Source Code in Deinem 1. Post: Bist Du sicher, dass FileViewer_Collection_ViewController ein Navigation Controller ist?

    Eigentlich lassen sich keine Navigation Controller auf den Stack eines Navigation Controllers pushen. Da sollte es zur Laufzeit eine Fehlermeldung geben und der Controller sollte sich dann nicht auf den Stack pushen lassen.
  • Ok, hier das Problem etwas genauer beschrieben:

    Das Projekt sieht wie folgt aus (Interface):
    [Blockierte Grafik: http://www.stachowiak-software.de/Forum/bild1.png]
    Link zum Bild zur Ansicht


    Der Navigationscontroller wird in einem Storyboard-Reference geladen. In dem Navigationscontroller werden Ordner und weiteres angezeigt. Wenn ich jetzt einen Ordner anklicke, wird ein zusätzlicher Navigationscontroller geladen. Mit folgendem Code

    C-Quellcode

    1. __weak typeof(self) weakSelf = self;
    2. FileViewer_Collection_ViewController* ViewerController = [weakSelf.storyboard instantiateViewControllerWithIdentifier:@"fileviewer_controller"];
    3. ViewerController = [weakSelf.storyboard instantiateViewControllerWithIdentifier:@"fileviewer_controller"];
    4. ViewerController.Pfad = [filename.filename_url path];
    5. ViewerController.title = filename.filename_str;
    6. [weakSelf.navigationController pushViewController:ViewerController animated:YES];
    Er lädt sich quasi selber noch einmal, mit der gleichen Klasse. Mein Problem stützt sich auf folgende Tatsache. Wenn ich jetzt von dem ersten zu einem neuen Navigationscontroller springe und wieder zurück springe, scheint sich der letzte Navigationscontroller nicht aus dem Speicher entfernen.

    So sieht der Vorgang im Simulator aus:
    [Blockierte Grafik: http://www.stachowiak-software.de/Forum/bild2.gif]
    Link zum Bild zur Ansicht

    Und das passiert in der Speicherverbrauchs-Anzeige bei Xcode:
    [Blockierte Grafik: http://www.stachowiak-software.de/Forum/bild3.gif]
    Link zum Bild zur Ansicht

    In Instruments (wo ich noch nicht wirklich durchblicke!) kann ich folgendes feststellen, falls es richtig ist:
    [Blockierte Grafik: http://www.stachowiak-software.de/Forum/bild4.gif]
    Link zum Bild zur Ansicht


    Ich würde davon ausgehen, dass die Funktion "Files_in_a_directory" nicht released wird oder? Leider werden die Bilder nicht angezeigt. Leider werden die Bilder anscheinend nicht angezeigt. Ich habe nochmals Links unter die Bilder gemacht!

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von necromonger ()

  • Wie gesagt, mit pushViewController:animated: lässt sich kein weiterer UINavigationController auf den Stack eines UINavigationControllers pushen. Dies führt zu einer Fehlermeldung zur Laufzeit.

    FileViewer_Collection_ViewController kann also keine Referenz auf ein UINavigationController sein.

    Ist dieser Source Code 1 zu 1 aus dem Projekt?

    Warum erzeugst Du 2 mal einen ViewController per [weakSelf.storyboard instantiateViewControllerWithIdentifier:@"fileviewer_controller"]?
  • Hallo MCDan,

    leider werden die Bilder nicht angezeigt. Ich habe nochmals Links davon gemacht. Eine Fehlermeldung bekomme ich nicht. Und es funktioniert auch tadellos, nur das der Speicher
    irgendwann überläuft. Auf den Bildern sieht man den Vorgang genau.

    Danke für den Tip. Das habe ich komplett übersehen. Zeile entfernt! Trotzdem ohne Wirkung!

    Gruss
    David
  • Hallo MCDan,

    Stimmt. FileViewer_Collection_ViewController ist ein UIViewController und kein UINavigationscontroller. Sorry, hatte mich vorher nicht korrekt ausgedrückt! Das wäre theoretisch so in Ordnung! Oder mache ich etwas beim Lade des 2. ViewControllers falsch oder habe ich einen Denkfehler?

    Gruss
    David

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