Xi 张熹
Xi 张熹

Reputation: 11071

Does iOS change reference of objects?

I don't have too much experience with iOS, but I am working on some legacy code. In the project, we use an object as the key of a dictionary:

NSMutableDictionary * dict;
RoleContainer * role = [Class getRole];
[dict setObject:[Class getData] forKey:role];

We have the role passed to another function. When we try to retrieve the data:

data = [dict objectForKey:role];

Sometimes the return value is empty. It happens about 10% of time. I stepped through the code and found out after passing role to the function the reference of the "role" object had been changed! For example, from 0x002bf500 to 0x00222bad.

Why?

Upvotes: 1

Views: 114

Answers (3)

vikingosegundo
vikingosegundo

Reputation: 52227

try

NSMutableDictionary * dict = [NSMutableDictionary dictionary];

Also it would make sense to have a look at your Class. Is it a class, and getRole a class-method? is it an object?

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726639

In order to play nicely with NSMutableDictionary your RoleContainer class must implement a hash and isEqual methods. Otherwise, equal roles may get recorded twice in the dictionary, or querying by a valid key may fail.

Here is a brief sample of how you could implement your hash/isEqual when your class has an identifying member:

@interface RoleContainer : NSObject
@property (nonatomic, readonly) NSString *name;
- (NSUInteger)hash;
- (BOOL)isEqual:(id)anObject;
@end

@implementation RoleContainer
@synthesize name = _name;
- (NSUInteger)hash {
    return [name hash];
}

- (BOOL)isEqual:(id)anObject {
    if (![anObject isKindOfClass:[RoleContainer class]]) {
        return NO;
    }
    RoleContainer *other = (RoleContainer*)anObject;
    return [_name isEqual:[other name]];
}
@end

Upvotes: 2

Derek
Derek

Reputation: 1170

In that code, dict is going to be nil, so you're sending messages to nothing. Is it actually pointing to something later on?

I'm assuming your RoleContainer responds to the stringValue method, which might be a good place to look at what is going on if it's overloaded.

If it's using the standard string value, then it's returning the class and memory location. This may not be reliable if someone down the line is resetting objects to keys.

You may also have an issue where the getData object is being released somewhere where it shouldn't be touched. Try enabling NSZombieEnabled in the debugger, or enable ARC.

Upvotes: 1

Related Questions