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

Solution

Find the path to your bundle at runtime using the pathForResource:ofType: method of your main bundle. Once you have the path to your bundle, simply access it using the bundleWithPath: class method of NSBundle.

Note

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.

Placing an image inside the bundle which we created before

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 pathForResource: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){

        UIImage *image = [UIImage imageWithContentsOfFile:pathToAlanSugarImage];

        if (image != nil){
          NSLog(@"Successfully loaded the image from the bundle.");
        } else {
          NSLog(@"Failed to load the image.");
        }

      } else {
        NSLog(@"Failed to find the file inside the bundle.");
      }

    } else {
      NSLog(@"Failed to load the bundle.");
    }

  } else {
    NSLog(@"Could not find the bundle.");
  }

  self.window = [[UIWindow alloc] initWithFrame:
                 [[UIScreen mainScreen] bounds]];

  self.window.backgroundColor = [UIColor whiteColor];
  [self.window makeKeyAndVisible];
  return YES;
}

If you are attempting to find all the resources which are stored in a specific folder inside a bundle, you can use the pathsForResourcesOfType:inDirectory: method of the NSBundle class. In this code, we will attempt to find the path to all the .png files inside the Images folder of our Resources.bundle bundle:

- (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){

      NSArray *PNGPaths = [resourcesBundle pathsForResourcesOfType:@"png"
                                                   inDirectory:@"images"];

      [PNGPaths
       enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
         NSLog(@"Path %lu = %@", (unsigned long)idx+1, obj);
       }];

    } else {
      NSLog(@"Failed to load the bundle.");
    }

  } else {
    NSLog(@"Could not find the bundle.");
  }

  self.window = [[UIWindow alloc] initWithFrame:
                 [[UIScreen mainScreen] bounds]];

  self.window.backgroundColor = [UIColor whiteColor];
  [self.window makeKeyAndVisible];
  return YES;
}

Note

the enumerateObjectsUsingBlock: method of NSArray accepts a block object as its parameter. For more information about enumerateObjectsUsingBlock: and the block object it accepts, please refer to Recipe 1.25.

Get iOS 6 Programming Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.