2010-04-06 10 views
2

J'ai une classe simple avec une variable membre NSMutableDictionary. Cependant, quand j'appelle setObject: forKey, je reçois une erreur ('méthode de mutation envoyée à l'objet immuable'). La source du problème est évidente à partir du débogueur - mon NSMutableDictionary est en fait de type NSDictionary.NSMutableDictionary est traité comme un NSDictionary

Il me manque quelque chose d'incroyablement simple mais je n'arrive pas à le résoudre. Voici le code correspondant:

// Model.h 
@interface Model : NSObject { 
    NSMutableDictionary *piers; 
} 
@property (nonatomic,retain) NSMutableDictionary *piers; 
@end 


// Model.m 
@implementation Model 
@synthesize piers; 

-(id) init { 
if (self = [super init]) { 
    self.piers = [[NSMutableDictionary alloc] initWithCapacity:2]; 
     [self createModel]; 
    } 
    return self; 
} 

-(void) createModel { 
[piers setObject:@"happy" forKey:@"foobar"]; 
} 
@end 

Si je mets un point d'arrêt partout dans le code et self.piers enquêter, il est de type NSDictionary. Que suis-je manquant pour qu'il soit traité comme un NSMutableDictionary à la place? Merci!

Répondre

0

Essayez d'enlever le self..

piers = [[NSMutableDictionary alloc] initWithCapacity:2]; 

Dans ObjC, la notation

obj.prop = sth; 

est équivalent à

[obj setProp:sth]; 

qui a totalement différent de sémantique

obj->prop = sth; 

Bien que hautement improbable, votre dictionnaire mutable devient probablement immuable pendant la procédure -setPiers:. Dites non à self.anything (jusqu'à ce que vous compreniez comment la propriété fonctionne).

+0

Merci pour votre réponse. Malheureusement, supprimer 'self' ne fonctionne pas. Quoi qu'il en soit, je comprends que je veux définir la propriété de soi appelée 'piers', donc je pourrais utiliser' -setPiers: 'ou' self.piers = '. Tout l'exemple de code d'Apple utilise 'self.property =' lors de l'initialisation des variables membres, donc j'ai suivi ce paradigme. Une autre chose à noter est que même sur les points d'arrêt qui se produisent avant l'exécution de l'assignation en question, 'piers' est affiché comme un NSDictionary dans le débogueur. – fractacular

+0

@Marc: Si vous appelez '[piers setObject: @" happy "forKey: @" foobar "];' directement dans '-init', cela aide-t-il? – kennytm

+0

WTF, je dois admettre que je n'ai pas complètement étudié votre suggestion - à la place je m'arrêtais sur mon point d'arrêt, notait que 'piers' était toujours un NSDictionary dans le débogueur, et pleurais à ce sujet.En fait, supprimer 'self' fonctionne, et l'appel' -setObject: forKey' fonctionne partout .... même avec ma variable en tant que NSDictionary. Maintenant, j'ai juste besoin de comprendre pourquoi éviter de «soi» dans ce cas - c'est partout dans le code d'Apple, ainsi que tous les constructeurs dans mon livre (Apress "Beginning iPhone 3 Dev."). Je suis noob, entendez-moi rugir. Thx :) – fractacular

1

Votre code fonctionne pour moi sans aucune modification. J'ai fait un outil en ligne de commande Foundation (Mac OS X) avec ce code:

#import <Foundation/Foundation.h> 

// Model.h 
@interface Model : NSObject { 
    NSMutableDictionary *piers; 
} 
@property (nonatomic,retain) NSMutableDictionary *piers; 

-(void) createModel; 

@end 


// Model.m 
@implementation Model 
@synthesize piers; 

-(id) init { 
    if (self = [super init]) { 
     self.piers = [[NSMutableDictionary alloc] initWithCapacity:2]; 
     [self createModel]; 
    } 
    return self; 
} 

-(void) createModel { 
    [piers setObject:@"happy" forKey:@"foobar"]; 
} 
@end 

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    // insert code here... 
    Model *model = [[Model alloc] init]; 

    NSLog(@"Model: %@", [model.piers objectForKey:@"foobar"]); 

    [pool drain]; 
    return 0; 
} 

et il m'a donné le résultat attendu:

2010-04-06 12: 10: 19,510 Modèle [3967 : a0f] Modèle: heureux

Comme le dit KennyTM, votre utilisation de soi-même est un peu faux. dans votre init, le schéma général est

NSMutableDictionary *aPiers = [[NSMutableDictionary alloc] initWithCapacity:2]; 
self.piers = aPiers; 
[aPiers release]; 

Plus tard dans le code, vous devez utiliser self.piers. Essayez un projet comme le mien et voyez si le problème persiste. Vous trouverez probablement que le problème est ailleurs.

+0

Merci - cela fonctionne. Et merci d'étendre la fuite de mémoire, que je vais éviter à partir de maintenant. – fractacular