2010-11-23 5 views
1

Je ne comprends pas pourquoi cela me donne un EXC_BAD_ACCESS. Arrière-plan de base, je recueille et traite certaines informations, puis utilise une vue modale pour laisser l'utilisateur confirmer s'il veut continuer.Iphone UIAlertView lance EXC_BAD_ACCESS. - Édité, pas causé par UIAlertView

J'ai un bouton dans la barre de navigation appelé continuer, qui appelle ma fonction de préparation de données.

- (void)viewDidLoad { 
    //Other stuff 
    UIBarButtonItem *next = [[UIBarButtonItem alloc] 
            initWithTitle:@"Next" 
            style:UIBarButtonItemStyleBordered 
            target:self 
            action:@selector(prepData)]; 
    self.navigationItem.rightBarButtonItem = next; 
    [next release]; 
    [super viewDidLoad]; 
} 

prepData:

-(void)prepData{ 
    /* 
    There's a bunch of stuff going on here, if "mensaje" is not an empty NSString, there is some kind of error that wont let me go on, if not, everything in the data is fine 
    */ 
    if(![mensaje isEqualToString:@""]){ 
     UIAlertView *alert = [[UIAlertView alloc] 
           initWithTitle:nil 
           message:mensaje 
           delegate:nil 
           cancelButtonTitle:@"Aceptar" 
           otherButtonTitles:nil]; 
     [alert show]; 
     [alert release]; 
    }else{ 
     UIActionSheet *actionSheet = [[UIActionSheet alloc] 
             initWithTitle:@"¿Esta seguro que desea realizar estas operaciones?" 
             delegate:self 
             cancelButtonTitle:@"Cancelar" 
             destructiveButtonTitle:@"Aceptar" 
             otherButtonTitles:nil]; 
     [actionSheet showInView:self.view]; 
     [actionSheet release]; 
    } 
} 

Si debugger, je peux faire tout le chemin à travers la prepData(), dès que je presse continue je reçois un EXC_BAD_ACCESS. Si je commente la [releaseSheet]; Je ne reçois pas l'exception, mais à ma connaissance, tout comme les vues d'alerte, les fiches d'action «restent» jusqu'à ce qu'elles s'affichent.

Au moins tous les livres que j'ai lus l'indiquent, mais il est tout à fait possible que je ne comprenne pas quelque chose dans le autoreleasing.

Juste pour référence, l'alerte apparaît très bien.

Quelqu'un at-il une idée de ce qui se passe ici?

Merci, Stefano. Editer: Compris, le code ci-dessus pour les feuilles d'actions et les vues d'alerte est très bien, le problème était que je libérais quelque chose qui a été plus tard essayant d'être auto-libéré.

Je boucle qui fait cela:

for(someConditions){ 
    NSString *montoFormateado = [[[NSString alloc] initWithFormat:@"%.2lf",[monto doubleValue]] stringByReplacingOccurrencesOfString:@"." withString:@","]; 
        [_postBuild setObject:[NSString stringWithString:montoFormateado] forKey:[NSString stringWithString:iidvar]]; 
        [montoFormateado release]; 
}        
postBuild = [_postBuild mutableCopy]; 
[_postBuild release]; 

Maintenant, il semble que l'erreur était dans le fait qu'en utilisant [NSString strintWithString: montoFormateado] je quittais cette chaîne pour autorelease plus tard, mais quand J'ai libéré _postBuild que la chaîne a été libérée aussi, j'ai enlevé cela et juste utilisé setObject: montoFormateado et son fonctionnement bien.

Sa mémoire qui fuit, mais je pense que c'est pour une question différente, l'exc_bad_access a été résolu.

+0

très petite chose, mais généralement je pense que c'est une meilleure idée d'appeler [super viewDidLoad] avant d'apporter des modifications, pas à la fin de la méthode. Le seul moment où vous voulez mettre [super xxx] à la fin d'une méthode est lorsque vous appelez dealloc. – makdad

+0

Merci pour le conseil, en changeant cela. Laissez-moi essayer avec des zombies pour voir si je reçois quelque chose. – blindstuff

+0

Le problème est très probablement dans le code que vous avez omis - peut-être que mensaje est publié trop souvent (c'est-à-dire libérant une chaîne autoreleased). – Eiko

Répondre

4

La manière la plus simple de trouver ce type de bogue consiste à utiliser la variable d'environnement NSZombieEnabled. Lorsque vous obtenez un EXC_BAD_ACCESS à la fin d'un appel, cela signifie généralement que quelque chose est autoeleased, mais son compte de retenue est déjà 0 lorsque vous l'avez libéré.

Vérifiez this post, cela vous sauvera la vie à plusieurs reprises. Si cela ne fonctionne pas, laissez un commentaire et nous remettrons nos bouchons de débogage sur :)

+0

J'ai accepté ceci parce que j'ai utilisé NSZombiesEnabled pour le résoudre, mais les réponses de Stephens et celles-ci sont correctes. – blindstuff

-1

Peut-être que vous libérons la UIAlertView avant son utilisé, essayez de supprimer la déclaration de libération et déclarer la UIAlertView que la libération automatique (si elle devrait être bien la façon dont vous l'avez)

if(![mensaje isEqualToString:@""]){ 
     UIAlertView *alert = [[UIAlertView alloc] 
           initWithTitle:nil 
           message:mensaje 
           delegate:nil 
           cancelButtonTitle:@"Aceptar" 
           otherButtonTitles:nil] autorelease]; 
     [alert show]; 

Une autre chose qu'il pourrait C'est que vous relâchez ces gars sur un rappel ou quelque chose, vous devriez vérifier que vous ne faites pas cela, et comme l'affiche ci-dessus m'a dit, vous pouvez utiliser des zombies pour comprendre ce genre de choses.

+0

Je crois que sa sortie de l'UIAlertView est bien. Les exemples de projets Apple que j'ai vus, utilisent les étapes suivantes pour afficher une vue d'alerte: 1. allouer le UIAlertView, 2. afficher le UIAlertView, 3. libérer le UIAlertView (tous dans la même portée). Les exemples de projets d'Apple J'ai également vu UIActionSheets libérer la feuille d'action après avoir appelé showInView. –

+0

-1 alloc/show/release est l'ordre correct. – Eiko

-1

Dans les deux cas, si vous allez "relâcher", mieux vaut "retenir" d'abord.

Dans le cas de l'UIActionSheet - je crois que la vue passée dans showInView conserve une copie de la feuille d'actions.

Dans AlertView, ce n'est pas le cas.

+0

-1 alloc/show/release est l'ordre correct. – Eiko

1

Je pense qu'il y a une version de trop dans le code que vous n'avez pas montrée (dans le "Il y a beaucoup de choses qui se passent ici, si" mensaje "n'est pas un bloc vide de NSString).

Il n'y a rien de mal avec votre code ActionSheet. Comme vous le dites, il devrait se désaffecter une fois qu'il n'est plus à l'écran. Mais si vous sur-libérez l'une des sous-vues de self.view, cela pourrait provoquer un plantage lorsque le pool de libération automatique est drainé.