A set is a collection that has no sense of order, and a particular object can only appear in a set once. Sets are primarily useful for asking the question “Is it in there?” For example, you might have a set of URLs that are not child-appropriate. Before displaying any web page to a child, you would want to do a quick check to see if the URL is in the set. Sets do this incredibly quickly.
An employee’s assets have no inherent order, and an asset should never appear twice in the same employee’s assets collection. Change your program to use an NSMutableSet instead of an NSMutableArray for the assets relationship.
In Employee.h, change the variable’s declaration:
#import "Person.h" @class Asset; @interface Employee : Person { int employeeID; NSMutableSet *assets; } @property int employeeID; - (void)addAssetsObject:(Asset *)a; - (unsigned int)valueOfAssets; @end
In Employee.m, create an instance of the correct class:
- (void)addAssetsObject:(Asset *)a { if (!assets) { assets = [[NSMutableSet alloc] init]; } [assets addObject:a]; [a setHolder:self]; }
Build and run the program. It should function the same.
You can’t access an object in a set by index because there is no sense of order in a set. Instead, all you can do is ask “Is there one of these in there?” NSSet has a method:
- (BOOL)containsObject:(id)x;
When you send this message to a set, it goes through its collection of objects looking for an object equal to x. If it finds one, it returns YES; otherwise it returns NO.
This brings us to a rather deep question: what does equal mean? The class NSObject defines a method called isEqual:. To check if two objects are equal, you use the isEqual: method:
if ([myDoctor isEqual:yourTennisPartner]) { NSLog(@"my doctor is equal to your tennis partner"); }
NSObject has a simple implementation of isEqual:. It looks like this:
- (BOOL)isEqual:(id)other { return (self == other); }
Thus, if you haven’t overridden isEqual:, the code snippet is equivalent to:
if (myDoctor == yourTennisPartner) { NSLog(@"my doctor is equal to your tennis partner"); }
Some classes override isEqual:. For example, in NSString, isEqual: is overridden to compare the characters in the string. For these classes, there is a difference between equal and identical. Let’s say I have two pointers to strings:
NSString *x = ... NSString *y = ...
x and y are identical if they contain the exact same address. x and y are equal if the strings they point to contain the same letters in the same order.
Thus, identical objects are always equal. Equal objects are not always identical.
Does this difference matter? Yes. For example, NSMutableArray has two methods:
- (NSUInteger)indexOfObject:(id)anObject;
- (NSUInteger)indexOfObjectIdenticalTo:(id)anObject;
The first steps through the collection asking each object “isEqual:anObject?” The second steps through the collection asking each object “== anObject”?