2011-04-08 1 views
0

Je rencontre des problèmes avec un singleton que j'ai créé. Il contient deux NSMutableDictionary, qui sont lus et utilisés dans trois vues (et quelques vues modales) dans toute l'application.Définition du dictionnaire dans singleton provoquant EXC_BAD_ACCESS

J'ai ajouté un MKMapView t tracer certains des lieux dans les dictionnaires sur une carte. Lorsque j'utilise exactement la même méthode/fonction utilisée dans toutes les autres vues pour accéder aux données, je reçois une erreur EXC_BAD_ACCESS relative à un dictionnaire désalloué. Cela vient de NSZombieEnabled:

CFDictionary retain: message sent to deallocated instance 

Dans une trace dsym'ed, il est le remplacement d'un dictionnaire avec un autre qui cause la douleur. Le code que je utilise pour appeler la fonction provient d'un clic de MKAnnotationView:

UIControl *tempButton = sender; 
NSString *selectedEventsString = [self.eventsArray objectAtIndex:tempButton.tag]; 
NSLog(@"eventString: %@", selectedEventsString); 
[[EventsManager eventsManager] changeSelectedEventsDictionaryTo:selectedEventsString]; 

[tempButton release]; 
[selectedEventsString release]; 

« selectedEventsString » sort à un événement parfaitement correspondant.

Le code correspondant à SELM:

-(void)changeSelectedEventsDictionaryTo:(NSString *)eventName { 
     NSLog(@"singleton: %@", eventName); 
     self.eventString = eventName; 
     self.selectedEventsDictionary = [self.eventsDictionary objectForKey:eventName]; 
} 

deux selectedEventsDictionary et eventsDictionary sont définis comme @property (nonatomic, conserver) dans le fichier .H, ce qui est la fonction d'initialisation:

+ (EventsManager*)eventsManager { 
    if (eventsManager == nil) { 
     eventsManager = [[super allocWithZone:NULL] init]; 
     eventsManager.eventsDictionary = [[NSMutableDictionary alloc] init]; 
     eventsManager.selectedEventsDictionary = [[NSMutableDictionary alloc] init]; 
     eventsManager.eventString = [[NSString alloc] init]; 
     eventsManager.mode = [[NSString alloc] init]; 
    } 

    return eventsManager; 
} 

Ceci est un exemple de code utilisé dans d'autres vues qui fonctionne très bien:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSUInteger row = [indexPath row]; 
    NSString *eventString = [self.eventsArray objectAtIndex:row]; 
    [[EventsManager eventsManager] changeSelectedEventsDictionaryTo:eventString]; 

    //Modal display code here 
} 

Toute aide serait grandement appréciée! Je pense que j'ai fourni tout le code pertinent, mais laissez-moi savoir si plus est nécessaire.

À la votre!

+0

Ok, juste résolu. Mais c'était vraiment bizarre. À un moment donné, je stockais un NSString supplémentaire dans MKAnnotationView pour afficher des données personnalisées. J'ai arrêté de l'utiliser, mais la variable était toujours déclarée dans le fichier .H. Quand je l'ai enlevé, tout est tombé en place. Étrange erreur étrange. – gamblor87

Répondre

1

Par où commencer! Je signalerai certaines choses que je vois mal.

Premier exemple. Ne libérez pas tempButton et selectedEventString car vous n'avez jamais explicitement appelé retain/copy ou alloc et init sur eux. Votre static eventsManager n'est pas thread-safe, ce qui peut ne pas poser de problème pour vous mais doit absolument être examiné.

Lire les commentaires pour le code exemple suivant

+ (EventsManager*)eventsManager { 
    if (eventsManager == nil) { //<-- Not thread safe 
     //DO NOT CALL SUPER USE self 
     //eventsManager = [[self alloc] init]; 
     eventsManager = [[super allocWithZone:NULL] init]; 

     //You need to autorelease these values or use an autoreleased static method 
     //eventsManager.eventsDictionary = [NSMutableDictionary dictionary]; 
     //eventsManager.selectedEventsDictionary = [NSMutableDictionary dictionary]; 
     eventsManager.eventsDictionary = [[NSMutableDictionary alloc] init]; 
     eventsManager.selectedEventsDictionary = [[NSMutableDictionary alloc] init]; 

     //Do not bother setting these at all or just set them to nil 
     eventsManager.eventString = [[NSString alloc] init]; 
     eventsManager.mode = [[NSString alloc] init]; 
    } 

    return eventsManager; 
} 

Assurez-vous que toutes ces propriétés sont définies à conserver ou à copier et qui peut résoudre votre problème. Si vous avez toujours un problème après ces corrections, vous pouvez mettre à jour votre question et je mettrai à jour ma réponse.

+0

Merci pour la bonne réponse. Je suis un novice et c'est la première fois que j'utilise vraiment des singletons, alors je suis toujours dans la tête. Modification de eventsManager = [[super allocWithZone: NULL] init]; à eventsManager = [[self alloc] init]; provoque un plantage lorsque j'essaie de faire quoi que ce soit avec EventsManager. Autres modifications implémentées (sauf thread-safe) sans changement de résultat. L'erreur NSZombie est: *** - [nombre CFDictionary]: message envoyé à l'instance désaffectée 0x2305f0 – gamblor87

+0

Ajoutons également que XCode indique qu'il s'agit d'eventsDictionary, et non de SelectedEventsDictionary. – gamblor87

+0

Joe, grâce à votre commentaire, j'ai re-fait que le singleton soit thread safe et se sent beaucoup plus confiant à ce sujet maintenant. Bien que cela n'ait pas semblé résoudre directement le problème, cela a sans aucun doute amélioré le programme et m'a permis d'être un meilleur programmeur. Alors merci! – gamblor87

Questions connexes