views:

815

answers:

3

If you store NSNumber* as a key to NSMutableDictionary, does it do the lookup later based on the key's address or stored value? It seems that if I store NSNumber in two dictionaries with the value from one serving as the key to the other, sometimes, the key isn't found in the 2nd dictionary even though I'm certain it's in there.

What I'm trying to do is the following:

// fetch the items from Coredata and create two different lookups
NSArray *existingActions = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

for (SomeObject *someObject in existingActions)
{
    NSNumber *actionId = [someObject actionId];
    [actionMap setObject:someObject forKey: actionId];

    NSNumber *positionId = [someObject positionId];
    [positionMap setObject: actionId forKey: positionId];
}

// later on, I'm trying to print out the values from both lookups now    
NSEnumerator *enumerator = [positionMap keyEnumerator];
NSNumber *positionId;

while ((positionId = (NSNumber *)[enumerator nextObject])) 
{
   NSNumber *actionId = (NSNumber *)[positionMap objectForKey:positionId];
   SomeObject * myObj =  (SomeObject *) [actionMap objectForKey:actionId];   

   NSLog(@"myObj: %@", myObj];
}   

// This way yields the same result as above:
NSNumber *positionId = [NSNumber numberWithInt: 7]; // filled out by client
NSNumber *actionId = (NSNumber *)[positionMap objectForKey:positionId];
SomeObject *myObj = (SomeObject *)[actionMap objectForKey: actionId];

Often, myObj is null because objectForKey can't seem to find the object associated with actionId in the actionMap dictionary.

As an additional note, the SomeObject class derives from 'NSManagedObject'. The documentation for setObject:forKey: notes for the parameters passed in:

aKey: The key for value. The key is copied (using copyWithZone:; keys must conform to the NSCopying protocol). The key must not be nil.

Is it due to the fact that copyWithZone may be different with NSManagedObject classes?

What am I doing wrong here?

+2  A: 

it uses the value that -hash returns.

NSResponder
When I try to get the hash value of NSNumber with '[actionId hash]', it returns null -- which doesn't seem right.
Alexi Groove
it can't return Null. You must be wrong
NSNumber *actionId = [someObject actionId];NSLog(@"hash: %@", [actionId hash]); ==> yields in the debug console:2009-10-08 15:18:14.229 MyTestApp[24644:20b] hash: (null)
Alexi Groove
- hash returns an NSUInteger. Your String format (%@) is incorrect.
With the correct format string, I see the expected hash value but same overall result of not finding the expected object in the NSDictionary.
Alexi Groove
A: 

You can use NSMapTable like an NSDictionary but without copying the keys

is this available for the iPhoneSDK? I'm having a hard time trying to link to it.
Alexi Groove
hmm it might not be. see this http://stackoverflow.com/questions/1095368/nsmaptable-missing-from-3-0-headers
+1  A: 

It turns out that the problem was from the fact that actionId property returned by [someObject actionId] is a weak reference and you can't store it in NSDictionary without making a copy of it.

Instead of:

NSNumber *actionId = [someObject actionId]; [actionMap setObject:someObject forKey: actionId];

this works:

NSNumber *actionId = [NSNumber numberWithInt: [[someObject actionId] intValue]]; [actionMap setObject:someObject forKey: actionId];

Alexi Groove