Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (3.67 MB, 89 trang )
You can see that we are using an index into the array to access each one of these values.
With dictionaries, we give each value a key, which is an object, and then use that key
to access those values. Let's see the same example, using dictionaries. We have a "First
Name" key with the value "Anthony" and so on:
NSNumber *age = [NSNumber numberWithUnsignedInteger:51];
NSDictionary *person = [[NSDictionary alloc] initWithObjectsAndKeys:
@"Anthony", @"First Name",
@"Robbins", @"Last Name",
age, @"Age",
nil];
NSLog(@"First Name = %@", [person objectForKey:@"First Name"]);
NSLog(@"Last Name = %@", [person objectForKey:@"Last Name"]);
NSLog(@"Age = %@", [person objectForKey:@"Age"]);
The results will then be printed out as shown here:
First Name = Anthony
Last Name = Robbins
Age = 51
As you can see, we initialized the dictionary with values and keys. We give a value
followed by the key for that value. When we used NSLog, we printed out each value by
handing the key to the dictionary's objectForKey: method.
The mutable version of NSDictionary, NSMutableDictionary, can be modified after it has
been allocated and initialized. For instance, if we want to remove the object associated
with the key Age from our dictionary after its initialization, we would use a mutable
dictionary like so:
NSNumber *age = [NSNumber numberWithUnsignedInteger:51];
NSMutableDictionary *person = [[NSMutableDictionary alloc]
initWithObjectsAndKeys:
@"Anthony", @"First Name",
@"Robbins", @"Last Name",
age, @"Age",
nil];
[person removeObjectForKey:@"Age"];
NSLog(@"First Name = %@", [person objectForKey:@"First Name"]);
NSLog(@"Last Name = %@", [person objectForKey:@"Last Name"]);
NSLog(@"Age = %@", [person objectForKey:@"Age"]);
We have simply removed the object associated with the key Age. The results printed to
the console window will be similar to this:
First Name = Anthony
Last Name = Robbins
Age = (null)
Note that "Age" is not just empty, but totally missing.
1.24 Allocating and Making Use of Dictionaries | 87
If you want to enumerate all keys with their objects inside a dictionary, you can simply
use the enumerateKeysAndObjectsUsingBlock: method of the dictionary. In the previous
array, the method would print the "First Name" and "Last Name" elements, but not
"Age", because we removed it. The parameter to this method is a block object with no
return value and three parameters:
Key
An id that tells you which key is being enumerated at the moment.
Object
An id as well, that gives you the object associated with the key being currently
enumerated.
A pointer to a value of type BOOL
At any point during the enumeration, if you want to stop the process, you can
simply put the value YES into this pointer's memory address. Keep it untouched if
you want to enumerate through all the keys in the dictionary.
Let's see an example:
NSNumber *age = [NSNumber numberWithUnsignedInteger:51];
NSDictionary *person = [[NSDictionary alloc] initWithObjectsAndKeys:
@"Anthony", @"First Name",
@"Robbins", @"Last Name",
age, @"Age",
nil];
[person enumerateKeysAndObjectsUsingBlock:
^(__strong id key, __strong id obj, BOOL *stop) {
NSLog(@"Key = %@, Object For Key = %@", key, obj);
}];
And the results, which get printed to the console window, are shown here:
Key = Last Name, Object For Key = Robbins
Key = First Name, Object For Key = Anthony
Key = Age, Object For Key = 51
If you want to do a manual fast enumeration without block objects, you can use the
allKeys method of the dictionary to go through all methods and, once you enumerate
the keys, use the keys to find the objects associated with the keys using the objectFor
Key: method, like so:
for (id keyInDictionary in [person allKeys]){
id objectForKey = [person objectForKey:keyInDictionary];
NSLog(@"Key = %@, Object For Key = %@", keyInDictionary, objectForKey);
}
Bear in mind that you can traverse the keys in a dictionary in various ways. We've just
seen two ways of doing this. There is another method that we can use: calling the
88 | Chapter 1: The Basics
keyEnumerator method of the dictionary to get an object of type NSEnumerator. Here is
an example:
NSEnumerator *keys = [person keyEnumerator];
id keyInDictionary = nil;
while ((keyInDictionary = [keys nextObject]) != nil){
id objectForKey = [person objectForKey:keyInDictionary];
NSLog(@"Key = %@, Object For Key = %@", keyInDictionary, objectForKey);
}
When using the keyEnumerator method of a mutable dictionary, you are
not allowed to change the values inside the dictionary while going
through the keys. The same rule, if you remember, applies to mutable
arrays as well.
See Also
XXX
1.25 Allocating and Making Use of Sets
Problem
You would like to store an array of objects but you don't want any one object to appear
more than once in the array.
Solution
Use sets instead of arrays.
Discussion
Sets are very similar to arrays. The big difference is that sets allow objects to be added
only once. The second time you try to add the same object, it will be rejected by the
set. We use NSSet for immutable and NSMutableSet for mutable sets. Let's have a look
at an example of an immutable set:
NSString *hisName = @"Robert";
NSString *hisLastName = @"Kiyosaki";
NSString *herName = @"Kim";
NSString *herLastName = @"Kiyosaki";
NSSet *setOfNames = [[NSSet alloc] initWithObjects:
hisName,
hisLastName,
herName,
1.25 Allocating and Making Use of Sets | 89
herLastName, nil];
NSLog(@"Set = %@", setOfNames);
We created an immutable set and passed 4 string objects to its initializer method. So
let's see what gets printed out to the console window with our NSLog:
Set = {(
Kim,
Robert,
Kiyosaki
)}
You can see that the last name Kiyosaki was added only once to the list. Our set rejected
the second addition of the same object to the list. It is very important to understand
that a set doesn't just do a comparison on where in memory an object sits, but it actually
looks into its contents. hisLastName and herLastName are two separate variables, and
they will sit in two different places in the memory. Our set, however, managed to
understand that we are passing instances of NSString to it and did a comparison on the
contents of these strings to find out that we had already added the Kiyosaki last name
to the set. So only one instance ended up in the set.
Now let's have a look at constructing mutable sets:
NSMutableSet *setOfNames = [[NSMutableSet alloc] initWithObjects:
hisName,
hisLastName, nil];
[setOfNames addObject:herName];
[setOfNames addObject:herLastName];
We simply used the addObject: method of NSMutableSet to add new objects to our set.
You can also use the removeObject: method to remove an object. Again, remember that
the contents of the object matter, not its memory address. So if you want to remove a
string from the set, simply pass that string to the removeObject: method, even if your
new string is in a different variable or somewhere else in memory. As long as the contents of that string/object are the same, you will get the results you want:
NSMutableSet *setOfNames = [[NSMutableSet alloc] initWithObjects:
hisName,
hisLastName,
herName,
herLastName, nil];
[setOfNames removeObject:@"Kiyosaki"];
NSLog(@"Set = %@", setOfNames);
And the results get printed to the console window:
Set = {(
Kim,
Robert
)}
90 | Chapter 1: The Basics