Objective-C Programming_ The Big Nerd Ranch Guide - Aaron Hillegass [43]
#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]; } NSMutableArray *allAssets = [[NSMutableArray alloc] init]; // 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]; [allAssets addObject:asset]; } NSLog(@"Employees: %@", employees); NSLog(@"Giving up ownership of one employee"); [employees removeObjectAtIndex:5]; NSLog(@"allAssets: %@", allAssets); NSLog(@"Giving up ownership of arrays"); allAssets = nil; employees = nil; } sleep(100); return 0; } Before you build and run your program, think about what you expect your output to look like. You’ll see the contents of the allAssets array – after Employee #5 has been deallocated. What will the status of Employee #5’s assets be at this point? These assets lose one owner (Employee #5), but they are still owned by allAssets, so they won’t be deallocated. What about holder for the assets previously owned by Employee #5? When the object that a weak reference points to is deallocated, the pointer variable is zeroed, or set to nil. So Employee #5’s assets will not be deallocated, and their holder variables will be automatically set to nil. Now build and run the program and check your output: Employees: ( " ... " ) Giving up ownership of one employee deallocating allAssets: ( " " " " " " " " " " ) Giving up ownership of arrays deallocing ... deallocing For the More Curious: Manual reference counting and ARC History [anObject release]; // anObject loses an owner [anObject retain]; // anObject gains an owner You would see these sorts of calls primarily in accessor methods (where the new value was retained and the old value was released) and in dealloc methods (where all the previously retained objects were released). The setHolder: method for Asset would have looked like this: - (void)setHolder:(Employee *)newEmp { [newEmp retain]; [holder release]; holder = newEmp; } The dealloc method would have looked
As mentioned at the beginning of Chapter 19, before automatic reference counting (ARC) was added to Objective-C, we had manual reference counting, which used retain counts. With manual reference counting, ownership changes only happened when you sent an explicit message to an object that decremented or incremented the retain count.