Reputation: 327
I have a custom class I'm using instances of as keys in a dictionary. The problem is, sometimes
(not all the time) requesting a value from a dictionary with one of my custom
instance keys returns nil
when the key really is in the dictionary. I looked
around the web on how to use custom objects as dictionary keys, and all I've
been able to find is that you need to implement the NSCopying
protocol, which
I have done.
My class looks like this:
// .h
@interface MyObject: NSObject <NSCopying>
@property (copy) NSString* someString;
@property (copy) NSString* otherString;
@property int someInt;
+ (instancetype) objectWithString:(NSString*)str;
- (id) copyWithZone:(NSZone*)zone;
@end
// .m
@implementation MyObject
@synthesize someString;
@synthesize otherString;
@synthesize someInt;
+ (instancetype) objectWithString:(NSString*)str {
id obj = [[self alloc] init];
[obj setSomeString:str];
[obj setOtherString:[str lowercaseString];
[obj setSomeInt:0];
return obj;
}
- (id) copyWithZone:(NSZone*)zone {
id other = [[[self class] allocWithZone:zone] init];
[other setSomeString:self.someString];
[other setOtherString:self.otherString];
[other setSomeInt:self.someInt];
return other;
}
@end
Then I put some of these things in a mutable dictionary like this:
MyObject* key1 = [MyObject objectWithString:@"Foo"];
MyObject* key2 = [MyObject objectWithString:@"Bar"];
NSNumber* value1 = [NSNumber numberWithInt:123];
NSNumber* value2 = [NSNumber numberWithInt:456];
NSMutableDictionary* theDict = [[NSMutableDictionary alloc] init];
[theDict setObject:value1 forKey:key1];
[theDict setObject:value2 forKey:key2];
Now what I want to do is just pop a key/value pair out of the dictionary, so I do that like this:
MyObject* theKey = [[theDict allKeys] firstObject];
NSNumber* theValue = [theDict objectForKey:theKey];
And here's where I run into problems. Most of the time, this works fine.
However, sometimes objectForKey:theKey
returns nil
. I've put a breakpoint
in my code and can confirm that theKey
is indeed in the theDict
.
What am I doing wrong here?
Upvotes: 4
Views: 2466
Reputation: 9012
You should also implement -isEqual:
and -hash
on your custom objects.
For more info: Apple Documentation, NSHipster article
The reason you must do this is the keys can be copied when you put them in the dictionary and the default implementation of isEqual
just does pointer comparison.
Upvotes: 6