Objets Mutable dans les collections

À partir des docs , Stocker des objects mutables dans des objects de collection peut causer des problèmes. Certaines collections peuvent devenir invalides ou même corrompues si elles contiennent des objects qui, par mutation, affectent la façon dont elles sont placées dans la collection. Premièrement, les propriétés des objects qui sont des keys dans des collections de hachage telles que des objects NSDictionary ou des objects NSSet, si elles sont modifiées, corrompent la collection si les propriétés modifiées affectent les résultats du hachage ou des methods isEqual: de l'object. (Si la méthode de hachage des objects de la collection ne dépend pas de leur état interne, la corruption est less probable.) Deuxièmement, si un object dans une collection ordonnée telle qu'un tableau sortingé a ses propriétés modifiées, cela peut affecter la façon dont l'object compare à d'autres objects dans le tableau, rendant ainsi l'ordre invalide.

Mais quand je consigne les résultats, l'object est parfaitement ajouté à la collection. En fait, ce n'est pas sûr?

-(void)mutableObjectsinCollections{ NSMutableArray *arr1 = [[NSMutableArray alloc]init]; NSMutableArray *arr2 = [[NSMutableArray alloc]init]; NSMutableArray *arr3 = [[NSMutableArray alloc]init]; NSMutableArray *arr4 = [[NSMutableArray alloc]init]; [self addObjectsToArrayBefore:arr1]; [self addObjectsToArrayBefore:arr2]; [self addObjectsToArrayBefore:arr3]; [self addObjectsToArrayBefore:arr4]; NSDictionary *dict = @{@"arr1": arr1,@"arr2": arr2,@"arr3": arr3,@"arr4": arr4,@"arr5": arr5}; NSLog(@"%@",dict); [self addObjectsToArrayAfter:arr1]; [self addObjectsToArrayAfter:arr2]; [self addObjectsToArrayAfter:arr3]; [self addObjectsToArrayAfter:arr4]; NSLog(@"%@",dict); } -(void)addObjectsToArrayBefore:(NSMutableArray *)arr{ for (int i = 1; i<10; i++) { [arr addObject:[NSNumber numberWithInteger:i]]; } } -(void)addObjectsToArrayAfter:(NSMutableArray *)arr{ for (int i = 10; i<20; i++) { [arr addObject:[NSNumber numberWithInteger:i]]; } } 

Je vais vous montrer un exemple.

Définissons notre propre key mutable pour un dictionary, notons qu'elle peut être copiée, elle définit une implémentation de hash et d'égalité.

 @interface MyKey : NSObject <NSCopying> @property (nonatomic, copy, readwrite) NSSsortingng *keyData; @end @implementation MyKey - (id)initWithData:(NSSsortingng *)data { self = [super init]; self.keyData = data; return self; } - (id)copyWithZone:(NSZone *)zone { MyKey *key = (MyKey *) [[[self class] alloc] init]; key.keyData = self.keyData; return key; } - (NSUInteger)hash { return self.keyData.length; } - (BOOL)isEqual:(id)object { if (![object isMemberOfClass:[self class]]) { return NO; } MyKey *key = object; return [self.keyData isEqualToSsortingng:key.keyData]; } @end 

Maintenant, passons à un cas de test simple:

Définissons quelques keys

 MyKey *key1 = [[MyKey alloc] initWithData:@"key1"]; MyKey *key2 = [[MyKey alloc] initWithData:@"key2"]; MyKey *keyX = [[MyKey alloc] initWithData:@"XXX"]; 

Et un dictionary simple

 NSDictionary *dictionary = @{key1: @"value1", key2: @"value2"}; 

Voyons voir ce qu'il y a à l'intérieur

 NSLog(@"%lu", (unsigned long) dictionary.count); NSLog(@"%@", dictionary); NSLog(@"%@", [dictionary objectForKey:key1]); NSLog(@"%@", [dictionary objectForKey:key2]); NSLog(@"%@", [dictionary objectForKey:keyX]); 

donne (attendu)

 2 { "<MyKey: 0x10010a8d0>" = value1; "<MyKey: 0x100108e40>" = value2; } value1 value2 (null) 

Changeons maintenant la valeur d'une key

 [(MyKey *)[[dictionary allKeys] objectAtIndex:0] setKeyData:@"XXX"]; 

Voyons ce qu'il y a à l'intérieur

 NSLog(@"%lu", (unsigned long) dictionary.count); NSLog(@"%@", dictionary); NSLog(@"%@", [dictionary objectForKey:key1]); NSLog(@"%@", [dictionary objectForKey:key2]); NSLog(@"%@", [dictionary objectForKey:keyX]); 

Donne

 2 //expected { "<MyKey: 0x10010a8d0>" = (null); //huh, null value? "<MyKey: 0x100108e40>" = value2; } (null) //huh? value2 (null) //huh? 

Qu'est ce qui ne s'est pas bien passé?

Les structures internes d'un dictionary sont implémentées à l'aide d'une table de hachage. Le hash de la key est utilisé pour searchr une valeur. Une fois que nous avons modifié datatables dans la key, la valeur de hachage changera également. Par conséquent, le dictionary ne pourra pas find la valeur stockée pour la key donnée.

Le code est sûr. NSDictionary ne se soucie pas de la mutabilité des valeurs dans les paires key-valeur. Ce que cela intéresse, c'est la mutabilité des keys qui dans votre cas sont de type NSSsortingng (immuable).

N'espérez pas non plus que si un problème de mutabilité existe réellement, il se manifestera avec une exception ou un crash. Il peut passer inaperçu juste donner des résultats incorrects lors de l'interrogation de la collecte, de sorte que le test que vous avez fait n'aide pas beaucoup.