I will show you an example.
Let's define our own mutable key for a dictionary, note it can be copied, it defines an implementation of hash
and of equality.
@interface MyKey : NSObject <NSCopying>
@property (nonatomic, copy, readwrite) NSString *keyData;
@end
@implementation MyKey
- (id)initWithData:(NSString *)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 isEqualToString:key.keyData];
}
@end
Now let's have a simple test case:
Let's define some keys
MyKey *key1 = [[MyKey alloc] initWithData:@"key1"];
MyKey *key2 = [[MyKey alloc] initWithData:@"key2"];
MyKey *keyX = [[MyKey alloc] initWithData:@"XXX"];
And a simple dictionary
NSDictionary *dictionary = @{key1: @"value1", key2: @"value2"};
Let's see what's inside
NSLog(@"%lu", (unsigned long) dictionary.count);
NSLog(@"%@", dictionary);
NSLog(@"%@", [dictionary objectForKey:key1]);
NSLog(@"%@", [dictionary objectForKey:key2]);
NSLog(@"%@", [dictionary objectForKey:keyX]);
gives (expected)
2
{
"<MyKey: 0x10010a8d0>" = value1;
"<MyKey: 0x100108e40>" = value2;
}
value1
value2
(null)
Let's now change the value of a key
[(MyKey *)[[dictionary allKeys] objectAtIndex:0] setKeyData:@"XXX"];
Let's see what's inside again
NSLog(@"%lu", (unsigned long) dictionary.count);
NSLog(@"%@", dictionary);
NSLog(@"%@", [dictionary objectForKey:key1]);
NSLog(@"%@", [dictionary objectForKey:key2]);
NSLog(@"%@", [dictionary objectForKey:keyX]);
Gives
2 //expected
{
"<MyKey: 0x10010a8d0>" = (null); //huh, null value?
"<MyKey: 0x100108e40>" = value2;
}
(null) //huh?
value2
(null) //huh?
What went wrong?
The internal structures of a dictionary are implemented using a hash table. The hash
of they key is used to search a value. Once we change the data in the key, the hash value will also change. As a result, the dictionary won't be able to find the value stored for the given key.