Pergunta

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?

Foi útil?

Solução

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top