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

Chapter 21 Collection Classes

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

"<Laptop 1: $17, assigned to <Employee 6: $119 in assets>>", "<Laptop 3: $51, assigned to <Employee 5: $136 in assets>>", "<Laptop 5: $85, assigned to <Employee 5: $136 in assets>>", "<Laptop 6: $102, assigned to <Employee 6: $119 in assets>>", "<Laptop 8: $136, assigned to <Employee 9: $136 in assets>>", "<Laptop 9: $153, assigned to <Employee 1: $153 in assets>>"

)

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

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.

138

NSSet/NSMutableSet

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 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.

139

Chapter 21 Collection Classes

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”?

NSDictionary/NSMutableDictionary

As you know, arrays are indexed by a number; it is easy to ask “Give me object 10.” Dictionaries are indexed by a string; it is easy to ask “Give me the object stored under the key favoriteColor.” More precisely, a dictionary is a collection of key-value pairs. The key is typically a string, and the value can be any sort of object. These key-value pairs are not kept in any particular order.

Let’s make a dictionary of executives. The key will be an executive title, and the value will be an instance of Employee. The first employee will be put in the dictionary under @"CEO"; the second under @"CTO". Change your main.m to create and populate the NSMutableDictionary. Then, print out the dictionary of executives. Finally, set the pointer to the dictionary to nil so that you can see the dictionary being deallocated.

140

NSDictionary/NSMutableDictionary

// Create an array of Employee objects

NSMutableArray *employees = [[NSMutableArray alloc] init];

// Create a dictionary of executives

NSMutableDictionary *executives = [[NSMutableDictionary 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];

//Is this the first employee?

if (i == 0) {

[executives setObject:person forKey:@"CEO"];

}

// Is this the second employee? if (i == 1) {

[executives setObject:person forKey:@"CTO"];

}

}

NSLog(@"allAssets: %@", allAssets);

NSLog(@"executives: %@", executives); executives = nil;

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. The executives dictionary should log itself out:

executives = {

CEO = "<Employee 0: $0 in assets>"; CTO = "<Employee 1: $153 in assets>";

}

141

) "" %% %

( ) * ""$ & G % 5 @-= % 6 5

( * ) =) ! & ) @ ) & * " )!

> ? 2AP ? " I #2AP ? ?$,

C O G ? ' @ ' # N O ? Y ? [' @ '$,

X O 0 0 # N O O Y ? [' @ '$,

? G ? @ I O %

+ 2+ '

( " @ ! B & ) + &) ) L K ) + '' ' " @ ! ( +& & ) !N6N! )' !N6Z !' & !

, & ) + ) )' .-!< ) + ) )N6N! 7

2AP ? " D I ##2AP ?$ $, # D N O #2A2 ) / =$$, # D N O #2A2 ) @ 6 4$$,

&& ' " &

K ) + & + " " ! B & ) ) & Q R L ( N6N! ! ( ; &N6N! @ ! G ; ' 7

!)

%%

2AP ? " I ##2AP ?$ $,

D ? # N O ?$,

C # N O$,

; # N O #2A2$$,

B # N O$,

&&

:; & & N6L " N6%! L " N6' " N6%! ' "! K ) + ) " !

!

This page intentionally left blank

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