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 )
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
If you want to fast enumerate all objects in a set, use the enumerateObjectsUsing
Block: method. The block object that you pass to this method should return no value
and should have two parameters:
A key of type id
Contains the object in the set that is being currently enumerated.
A pointer to a boolean value of type BOOL
If you want to stop the enumeration at any time, simply place a boolean value of
type YES into the memory address of this variable.
Let's have a look at an example. Let's say I want to try to find the string Kiyosaki in a
set that I have:
[setOfNames enumerateObjectsUsingBlock:^(__strong id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSString class]]){
NSString *string = (NSString *)obj;
if ([string isEqualToString:@"Kiyosaki"]){
NSLog(@"Found %@ in the set", string);
*stop = YES;
}
}
}];
If the enumeration can find a string with the value of Kiyosaki in the set, we print a
string to the console and terminate the enumeration by placing the value of YES into
the second parameter of our enumerator block object.
There are other handy methods for sets. Use the count method to get the number of
objects currently in a set. You can also use the allObjects method to get an array of all
the objects in the set. If you want to extract an object from the set, with no concern or
which one, call the anyObject on your set. This method will return, as its name implies,
a random object in the set, no matter where in the set it is. You will get nil from this
method if the set is empty.
Remember that an immutable empty set is absolutely useless. It's empty
and it will remain empty throughout its lifetime.
See Also
XXX
1.25 Allocating and Making Use of Sets | 91
1.26 Creating Bundles
Problem
You want to group your resources into hierarchical structures and be able to access
those resources at run time with ease.
Solution
Follow these steps to successfully create a bundle:
1. Create a root folder on your disk that will later become your bundle. For instance,
let's give this folder the name Resources.
2. Under the Resources folder, create three more folders named Images, Videos, and
Sounds.
3. Under the three aforementioned folders, place related resources. For instance,
place one or more images in the Images folder and one or more video files under
the Videos folder and so on.
4. Once you are done, rename your Resources folder to Resources.bundle. Once you
add this extension to your folder name, OS X will ask for your confirmation and a
dialog similar to that shown in Figure 1-33 will appear on the screen. Press Add on
the dialog to add the .bundle extension to the Resources folder.
Figure 1-33. Adding a .bundle extension to a folder name in order to turn it into a bundle
Discussion
Bundles are simple folders with a .bundle extension. They have two main distinctions
from regular folders:
1. Cocoa Touch provides an interface through which you can access bundles and
their resources really easily.
92 | Chapter 1: The Basics
2. If a bundle is added to the Navigator on the left hand side of Xcode, any files added
to or removed from the bundle outside Xcode will, respectively, appear in or disappear immediately from Xcode's navigator. In contrast, if you had added a normal
folder to Xcode's navigator and then went and deleted a file from that folder on
disk, without using Xcode's help, you would see that file marked with red color in
Xcode rather than getting deleted immediately. Bundles can be very useful, especially if you want to add files to your folders manually using Finder, instead of using
Xcode.
Every iOS application comes with at least one bundle, called the main bundle. The
main bundle contains your app's binary code and any other resource you are using
inside your application, such as retina images, sounds, HTML files, and whatnot. The
main bundle, in other words, contains the resources that get compiled into your final
binary that you will submit to the App Store or distribute in your organization. These
resources can then be dynamically loaded using the NSBundle class's mainBundle class
method.
Although you can add two or more bundles with the same name to one
iOS project, it is best not to complicate things like that. The reason this
situation could get complicated is that when we start loading resources
from our bundles, we will first need to find our bundles by their path.
If you have two bundles with the same name, it will become quite difficult to detect which is which. So as a good practice, make sure that
your bundles have different names when you add them to your Xcode
projects.
See Also
XXX
1.27 Loading Data From the Main Bundle
Problem
You have added a resource (such as an image) to your Xcode project and now, at run
time, you would like to access that resource.
Solution
Use the mainBundle class method of the NSBundle class in order to retrieve your main
bundle. Once that is done, use the pathForResource:ofType: method of your main
bundle to retrieve the path for that specific resource. Once the path is detected, depending on the type of resource, you can either pass the path to your file to a class such
as UIImage or NSData, or you can manually access the file using NSFileManager.
1.27 Loading Data From the Main Bundle | 93
It is highly recommended that you give a unique name to each resource
inside your bundles. For instance, it is not good practice to have a file
named Default.png in more than one place inside your main bundle.
Different ways of loading a resource from a bundle could then yield
different results. As a result, make sure you give unique names to your
files inside any bundle, regardless of whether it is the main bundle or a
custom bundle that you've created (see Recipe 1.26).
Discussion
To access the main bundle, we can use the mainBundle class method of the NSBundle
class. Bundles are all of type NSBundle and once you have an instance of a bundle, you
can load resources from that bundle.
Every app's main bundle has a flat hierarchy on disk when it is compiled
for submission to App Store. That means all the files that get wrapped
up in your app bundle will be placed on the root folder of the main
bundle. In other words, the main bundle has only one folder, the root
folder, and all files and resources are stored in that folder. Even if you
have a folder on disk with a few images in it and drag and drop it into
Xcode, only the files in that folder will be placed in the main bundle's
file hierarchy, not the folder itself.
For instance, let's say that you have an image called AlanSugar.png sitting on your
desktop. Simply drag and drop it into Xcode. At this point, Xcode will display a dialog
to you, asking you which project this file has to be added to and whether you want this
file to be copied over to the project's folder, if need be. This dialog will look similar to
that shown in Figure 1-34.
94 | Chapter 1: The Basics