Reputation: 3586
I am very new to Objective-C and I have come across the NSMutableDictionary. I want to insert an object into the key and from my understanding, you need to make a copy by using the NSCopying class.
I have been reading the Apple's Documentations and I am still puzzled with this. Also I have been searching for examples and I can only seem to find ones that have keys as NSString objects which seems to be automatically copied.
Here is the part of my implementation code:
@implementation League
- (void) setPlayerInTeam: (Club*) theClub playerObject: (Person*) person{
[playerTeam setObject:theClub forKey: person];
}
@end
the forKey:person is obviously wrong, how do I make a copy of this by using the NSCopying? Sorry for being a newbie but I am eager to learn.
Many thanks.
Upvotes: 0
Views: 705
Reputation: 86651
The keys you use in an NSMutableDictionary have certain restrictions. NSMutableDictionary copies the key when you use -setObject:forKey:
. This means the key must support the NSCopying protocol. So Person needs to be declared like this:
@interface Person : PersonsSuperClass <NSCopying>
and it needs to implement the method -copyWithZone:
If the Person class is immutable and you are using ARC, -copyWithZone:
can simply return self
.
-(id) copyWithZone: (NSZone*) zone
{
return self; // or return [self retain] if not using ARC.
}
If Person is not immutable, -copyWithZone:
needs to make a new Person object that is exactly the same as the one you are copying.
-(id) copyWithZone: (NSZone*) zone
{
Person* theCopy = [[[self class] allocWithZone: zone] init];
// copy all the data from self to theCopy
return theCopy;
}
There are some other things you need to be careful of too. The method -isEqual:
must be semantically correct because that is how comparisons are done by NSMutableDictionary. For example, if a Person is uniquely indexed by a property called userId, you need to make -isEqual:
use that property to determine if two Person object are equal. A similar rule exists for -hash
, two objects that compare equal using -isEqual:
must have the same hash.
Upvotes: 1
Reputation: 42588
As Hot Licks said, you must create a -[Person copyWithZone:]
method.
@interface Person : NSObject <NSCopying>
@property NSString *firstName;
@property NSString *lastName;
…
@end
@implementation
- (id)copyWithZone:(NSZone *)zone
{
Person *copy = [[[self class] allocWithZone:zone] init];
if (copy) {
copy->_firstName = [self.firstName copyWithZone:zone];
copy->_lastName = [self.lastName copyWithZone:zone];
…
}
return copy;
}
@end
It's a real pain and full of possible subtle defects. In addition, I would highly recommend creating -[Person isEqual:]
and -[Person hash]
methods to avoid other types of defects.
Sometimes it's a must, but avoid it when possible.
Upvotes: 0