Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Objective-C.Programming.pdf
Скачиваний:
14
Добавлен:
21.02.2016
Размер:
8.64 Mб
Скачать

21

Collection Classes

You have already used two collection classes: NSArray and its subclass NSMutableArray. As you know, an array holds a collection of pointers to other objects. The pointers are ordered, so you use an index (an integer) to access the objects in the collection. In this chapter, we will delve deeper into arrays and look at some other collection classes: NSSet/NSMutableSet and NSDictionary/NSMutableDictionary.

NSArray/NSMutableArray

When you add an object to an array, the array claims ownership of it. When you remove the object from the array, the array gives up ownership. Open BMITime, and take a look at how you are using the employees array. If we ignore all the other stuff, you see something like this:

// 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];

// Put the employee in the employees array [employees addObject:person];

}

[employees removeObjectAtIndex:5]; employees = nil;

You typically create an empty mutable array using alloc/init or the class method array. For example, you could have created the mutable array like this:

NSMutableArray *employees = [NSMutableArray array];

Note that the addObject: method adds the object to the end of the list. As objects are added, an array will grow as big as necessary to hold them.

Immutable objects

When you create an instance of NSArray, you assign all its objects to it when it is created. This typically looks like this:

NSArray *colors = [NSArray arrayWithObjects:@"Orange", @"Yellow", @"Green", nil];

135

Chapter 21 Collection Classes

The nil at the end is how you tell the method to stop. Thus, this colors array would only have three strings. (If you forget the nil, it will probably crash your program.)

Most beginning programmers are surprised by the existence of NSArray. Why would anyone want a list that can’t be changed? There are two reasons:

You don’t trust the people you work with. That is, you want to let them look at an array, but you don’t want them to be able change it. A gentler approach is to give them an NSMutableArray, but tell them it is an NSArray. For example, imagine the following method:

// Returns

an array of 30

odd numbers

- (NSArray

*)odds

 

{

 

 

static

NSMutableArray

*odds = [[NSMutableArray alloc] init];

int i

= 1;

 

while

([odds count] <

30) {

[odds addObject:[NSNumber numberWithInt:i];

i

+= 2;

 

}

return odds;

}

Anyone calling this method assumes it is returning an immutable NSArray. If the caller tries to add or remove items from the returned object, the compiler will issue a stern warning – even though, it is, in fact, an instance of NSMutableArray.

The other reason is performance: an immutable object never needs to be copied. With a mutable object, you might make a private copy so that you know that no other code in the system can change it from underneath you. This is unnecessary for immutable objects. In fact, while the copy method of NSMutableArray makes a new copy of itself and returns a pointer to the new array, the copy method

of NSArray does nothing – it just returns a pointer to itself.

As a result, immutable objects are fairly common in Objective-C programming. In Foundation, there are many classes that create immutable instances: NSArray, NSString, NSAttributedString, NSData,

NSCharacterSet, NSDictionary, NSSet, NSIndexSet, and NSURLRequest. All of these have mutable

subclasses: NSMutableArray, NSMutableString, NSMutableAttributedString, etc. NSDate and

NSNumber, on the other hand, are immutable but don’t have mutable subclasses.

Sorting

There are several ways to sort an array, but the most common way is to use an array of sort descriptors. NSMutableArray has the following method:

- (void)sortUsingDescriptors:(NSArray *)sortDescriptors;

The argument is an array of NSSortDescriptor objects. A sort descriptor has the name of a property of the objects contained in the array and whether that property should be sorted in ascending or descending order. Why do we pass an array of sort descriptors? Imagine you said, “Sort this list of doctors by last name in ascending order.” What if two doctors have the same last name? You can specify “Sort by last name ascending, and if the last names are the same, sort by first name ascending, and if the first and last names are the same, sort by zip code.”

136

Filtering

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: (

"<Employee 0: $0 in assets>", "<Employee 4: $0 in assets>", "<Employee 8: $0 in assets>", "<Employee 7: $34 in assets>", "<Employee 3: $68 in assets>", "<Employee 2: $119 in assets>", "<Employee 6: $119 in assets>", "<Employee 5: $136 in assets>", "<Employee 9: $136 in assets>", "<Employee 1: $153 in assets>"

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:

137

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]