Débuguer un EXC_BAD_ACCESS aléatoire

muqaddarmuqaddar Administrateur
décembre 2014 modifié dans API UIKit #1

Salut,


 


Je n'arrive pas à  m'en sortir pour démasquer un bug-plantage lors de la suppression d'une cellule dans une UITableView.


 


Le problème, c'est que Xcode m'affiche le main() avec un EXC_BAD_ACCESS.


 


J'ai essayé des pointeurs un peu partout dans le VC sans succès. D'autant plus que le bug est irrégulier, et que les pointeurs et leurs arrêts ont l'air "d'améliorer les choses".


 


J'ai pensé à  un problème de mémoire, et j'ai passé quelques refs à  strong sans succès.


 


Le datasource est bien mis à  jour après la suppression de la cellule, puis un bête reloadData sur la UITableView. Je ne crois pas que ce soit un problème de sections et de rows.


 


J'ai aussi rajouté un All Exceptions breakpoint dans Xcode, mais je reste dans main() lors des plantages.


 


Si vous avez des conseils dans ces cas-là , puisque le pas à  pas avec Breakpoints ne m'apporte rien.


Réponses

  • Joanna CarterJoanna Carter Membre, Modérateur
    décembre 2014 modifié #2

    Le datasource, c'est quoi ; array ou Core Data ?


     


    Et comment supprimes-toi la cellule ?


  • AliGatorAliGator Membre, Modérateur
    Un "Analyze" ne donne pas de warning pouvant mettre sur la piste ?
  • AliGatorAliGator Membre, Modérateur
    Et sinon en activant les zombies pour voir quel objet fait planter ça devrait aider.
  • muqaddarmuqaddar Administrateur
    décembre 2014 modifié #5


    Le datasource, c'est quoi ; array ou Core Data ?




     


    C'est un array d'arrays que je construis moi-même dans une méthode à  part.


     




    Et comment supprimes-toi la cellule ?





    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
    {
      NSArray *rows = [self.datasource objectAtIndex:indexPath.section];
      NSDictionary *dict = [rows objectAtIndex:indexPath.row];
      NSUInteger field = [[dict objectForKey:KEY_FIELD] intValue];

      if (editingStyle == UITableViewCellEditingStyleDelete)
      {
        if (field == KEY_CELLAR_FIELD)
        {
          // remove a cellar
          [((Cellar*)[dict objectForKey:KEY_OBJECT]) removeFromClient];
          [self reloadData];
        }
        if (field == KEY_SHELF_FIELD)
        {
          // remove a shelf
          [((Shelf*)[dict objectForKey:KEY_OBJECT]) removeFromClient];
          [self reloadData];
        }
      }
    }

    L'instance du modèle est bien supprimée.


    Le reloadData est appelé ET exécuté entièrement.


    En mettant des pointeurs dans les méthodes de UITableView datasource, je ne trouve rien de particulier.


  • muqaddarmuqaddar Administrateur
    décembre 2014 modifié #6


    Et sinon en activant les zombies pour voir quel objet fait planter ça devrait aider.




     


    Ah voilà , je viens de les activer.


    J'y vois beaucoup plus clair, du moins j'ai une piste.


     


    2014-12-31 14:20:37.368 VinoCellD[4576:5135232] *** -[MenuTableViewCell _setDeleteAnimationInProgress:]: message sent to deallocated instance 0x7fe102aa1780

     


    J'imagine qu'il essaie d'animer la cellule alors que j'ai déjà  fait un reloadData sur la table ?


     


    En effet, quand je supprime une cellule (et donc un objet associé), je recalcule tout mon datasource (qui s'en trouvé "décalé") et je reload la table.


  • muqaddarmuqaddar Administrateur
    décembre 2014 modifié #7

    ça a l'air beaucoup mieux comme ça:



    if (field == KEY_CELLAR_FIELD)
    {
          // remove a cellar in model
          if ([((Cellar*)[dict objectForKey:KEY_OBJECT]) removeFromClient])
          {
            // remove in datasource
            [self.datasource removeObjectAtIndex:indexPath.section];
            // reload sections
            [self.tableView beginUpdates];
            [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView endUpdates];
    }
    }

    Je faisais un reload complet du datasource puis de la table parce que j'avais l'impression que mon datasource était trop compliqué et qu'il fallait tout recalculer et refaire un refresh sur toute la table.


     


    Alors qu'en fait, ça marche très bien, "avec la méthode officielle".


    Dommage que je n'ai pas activé les zombies plus tôt, je ne savais plus où c'était.


Connectez-vous ou Inscrivez-vous pour répondre.