Objective-C Programming_ The Big Nerd Ranch Guide - Aaron Hillegass [46]
Figure 21.1 Sort by lastName, then firstName, then zipCode
The property you sort on can be any instance variable or the result of any method of the object.
Let’s return to the BMITime project to see sorting in practice. In main(), just before logging the employees array, sort it by valueOfAssets. If two employees are holding assets of the same value, sort them by employeeID. Edit main.m:
}
NSSortDescriptor *voa = [NSSortDescriptor sortDescriptorWithKey:@"valueOfAssets"
ascending:YES];
NSSortDescriptor *ei = [NSSortDescriptor sortDescriptorWithKey:@"employeeID"
ascending:YES];
[employees sortUsingDescriptors:[NSArray arrayWithObjects:voa, ei, nil]];
NSLog(@"Employees: %@", employees);
Build and run the program. You should see the employees list ordered correctly:
Employees: (
" " " " " " " " " " Filtering There is a class called NSPredicate. A predicate contains a statement that might be true, like “The employeeID is greater than 75.” NSMutableArray has a handy method for discarding all the objects that don’t satisfy the predicate: - (void)filterUsingPredicate:(NSPredicate *)predicate; NSArray has a method that creates a new array that contains all the objects that satisfy the predicate: - (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate; Imagine that you are going to reclaim all the assets given to employees who currently hold assets worth more than $70 total. Add the code near the end of main.m: [employees removeObjectAtIndex:5]; NSLog(@"allAssets: %@", allAssets); NSPredicate *predicate = [NSPredicate predicateWithFormat: @"holder.valueOfAssets > 70"]; NSArray *toBeReclaimed = [allAssets filteredArrayUsingPredicate:predicate]; NSLog(@"toBeReclaimed: %@", toBeReclaimed); toBeReclaimed = nil; NSLog(@"Giving up ownership of arrays"); allAssets = nil; employees = nil; } return 0; } Build and run the program. You should see a list of assets: toBeReclaimed: ( " " " " " " ) The format string used to create the predicate can be very complex. If you do a lot of filtering of collections, be sure to read Apple’s Predicate Programming Guide. NSSet/NSMutableSet 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. Figure 21.2 Using NSMutableSet for assets 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
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.