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?
asked Sep 15 '25 23:09
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With