Objective-C Programming_ The Big Nerd Ranch Guide - Aaron Hillegass [40]
When an object is added to the collection, the collection establishes a pointer to the object, and the object gains an owner.
When an object is removed from a collection, the collection gets rid of its pointer to the object, and the object loses an owner.
To set up the to-many relationship in Employee, you’ll need a new instance variable to hold a pointer to the mutable array of assets. You’ll also need a couple of methods. Open Employee.h and add them:
#import "Person.h"
@class Asset;
@interface Employee : Person
{
int employeeID;
NSMutableArray *assets;
}
@property int employeeID;
- (void)addAssetsObject:(Asset *)a;
- (unsigned int)valueOfAssets;
@end
Notice the line that says @class Asset;. As the compiler is reading this file, it will come across the class name Asset. If it doesn’t know about the class, it will throw an error. The @class Asset; line tells the compiler “There is a class called Asset. Don’t panic when you see it in this file. That’s all you need to know for now.”
Using @class instead of #import gives the compiler less information, but makes the processing of this particular file faster. You can use @class with Employee.h and other header files because the compiler doesn’t need to know a lot to process a file of declarations.
Now turn your attention to Employee.m. With a to-many relationship, you need to create the collection object (an array, in our case) before you put anything in it. You can do this when the original object (an employee) is first created, or you can be lazy and wait until the collection is needed. Let’s be lazy.
#import "Employee.h"
#import "Asset.h"
@implementation Employee
@synthesize employeeID;
- (void)addAssetsObject:(Asset *)a
{
// Is assets nil?
if (!assets) {
// Create the array
assets = [[NSMutableArray alloc] init];
}
[assets addObject:a];
}
- (unsigned int)valueOfAssets
{
// Sum up the resale value of the assets
unsigned int sum = 0;
for (Asset *a in assets) {
sum += [a resaleValue];
}
return sum;
}
- (float)bodyMassIndex
{
float normalBMI = [super bodyMassIndex];
return normalBMI * 0.9;
}
- (NSString *)description
{
return [NSString stringWithFormat:@" [self employeeID], [self valueOfAssets]]; } - (void)dealloc { NSLog(@"deallocating %@", self); } @end To process the Employee.m file, the compiler needs to know a lot about the Asset class. Thus, you imported Asset.h instead of using @class. Also notice that you overrode description and dealloc to track the deallocation of Employee instances. Build the project to see if you’ve made any mistakes. Now you need to create some assets and assign them to employees. Edit main.m: #import #import "Employee.h" #import "Asset.h" int main(int argc, const char * argv[]) { @autoreleasepool { // Create an array of Employee objects NSMutableArray *employees = [[NSMutableArray alloc] init]; for (int i = 0; i < 10; i++) { // Create an instance of Employee Employee *person = [[Employee alloc] init]; // Give the instance variables interesting values [person setWeightInKilos:90 + i]; [person setHeightInMeters:1.8 - i/10.0]; [person setEmployeeID:i]; // Put the employee in the employees array [employees addObject:person]; } // Create 10 assets for (int i = 0; i < 10; i++) { // Create an asset Asset *asset = [[Asset alloc] init]; // Give it an interesting label NSString *currentLabel = [NSString stringWithFormat:@"Laptop %d", i]; [asset setLabel:currentLabel]; [asset setResaleValue:i * 17]; // Get a random number between 0 and 9 inclusive NSUInteger randomIndex = random() % [employees count]; // Find that employee Employee *randomEmployee = [employees objectAtIndex:randomIndex]; // Assign the asset to the employee [randomEmployee addAssetsObject:asset]; } NSLog(@"Employees: %@", employees);