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 )
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
Figure 1-34. Xcode asking which project a file has to be added to
In this dialog, make sure that the "Copy items into destination group's folder (if needed)" item is selected. This will copy the file that you drop into Xcode to the target
app's folder. Now, if you delete the file on your desktop, it won't get deleted from your
project because your project has its own copy. It's generally good practice to do this
unless for specific reasons you decide not to (and I've experienced many of these reasons
myself). After you drag and drop the file, the file AlanSugar.png is in the project's main
bundle and you can retrieve its path in this way:
- (BOOL)
application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSString *alanSugarFilePath =
[[NSBundle mainBundle] pathForResource:@"AlanSugar"
ofType:@"png"];
if ([alanSugarFilePath length] > 0){
UIImage *image = [UIImage imageWithContentsOfFile:alanSugarFilePath];
if (image != nil){
NSLog(@"Successfully loaded the file as an image.");
} else {
NSLog(@"Failed to load the file as an image.");
}
} else {
NSLog(@"Could not find this file in the main bundle.");
1.27 Loading Data From the Main Bundle | 95
}
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
The output of the pathForResource:ofType: method of NSBundle will be either a valid
path or nil if the specified resource cannot be found in the target bundle. So after you
call this method, it is best to check whether the path could actually be retrieved. If so,
the code shown passes the path of the file to the UIImage class in order to load the
AlanSugar.png file into memory as an image.
Similarly, if you wanted to load the data of that file into memory, instead of retrieving
this image as an image object, you could use the NSData class:
- (BOOL)
application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSString *alanSugarFilePath =
[[NSBundle mainBundle] pathForResource:@"AlanSugar"
ofType:@"png"];
if ([alanSugarFilePath length] > 0){
NSError *readError = nil;
NSData *dataForFile =
[[NSData alloc] initWithContentsOfFile:alanSugarFilePath
options:NSMappedRead
error:&readError];
if (readError == nil &&
dataForFile != nil){
NSLog(@"Successfully loaded the data.");
} else if (readError == nil &&
dataForFile == nil){
NSLog(@"No data could be loaded.");
} else {
NSLog(@"An error occured while loading data. Error = %@", readError);
}
} else {
NSLog(@"Could not find this file in the main bundle.");
}
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
96 | Chapter 1: The Basics
}
return YES;
See Also
XXX
1.28 Loading Data From Other Bundles
Problem
You have included a few images or other resources in a separate bundle inside your
main bundle and you would like to access those resources at run time.
Solution
Find the path to your bundle at run time using the pathForResource:ofType: method
of your your main bundle. Once you have the path to your bundle, simply access it
using the bundleWithPath: class method of NSBundle.
Before continuing with this recipe, please follow the instructions in
Recipe 1.26 to create a bundle called Resources.bundle and place it inside
your main bundle.
Discussion
If you have followed the instructions in Recipe 1.26, you now have a bundle called
Resources.bundle inside this bundle you have a folder called Images. Let's now put an
image inside this folder. After I placed an image called AlanSugar.png into the bundle
Figure 1-35 shows what the bundle contains.
1.28 Loading Data From Other Bundles | 97
Figure 1-35. Placing an image inside the bundle which we created before
Since the Resources.bundle is added to our app's main bundle, we will need to use the
main bundle in order to find the path to our Resources.bundle. Once that is done, we
can directly access the files (only AlanSugar.png right now) inside this bundle. Since
bundles other than the main bundle can have folders embedded inside them, to access
files inside folders of a bundle other than the main bundle it is best to use the pathFor
Resource:ofType:inDirectory: method of NSBundle to explicitly specify the folder in
which a specific file/resource exists.
- (BOOL)
application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSString *resourcesBundlePath =
[[NSBundle mainBundle] pathForResource:@"Resources"
ofType:@"bundle"];
if ([resourcesBundlePath length] > 0){
NSBundle *resourcesBundle = [NSBundle bundleWithPath:resourcesBundlePath];
if (resourcesBundle != nil){
NSString *pathToAlanSugarImage =
[resourcesBundle pathForResource:@"AlanSugar"
ofType:@"png"
inDirectory:@"Images"];
if ([pathToAlanSugarImage length] > 0){
98 | Chapter 1: The Basics