0

I have created a subproject as a static library and added a bundle to it, so I can wrap the project and resources that will be used by all programs using that library.

I have followed the instructions here. http://www.galloway.me.uk/tutorials/ios-library-with-resources/

It is working fine, except when I have to work with resources like images and other files.

I thought that by importing a library and its resources to another project I could access them easily but this is not the case.

Every time I have to access a resource file on library's bundle I have to use this:

NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"MyLibraryBundle" withExtension:@"bundle"]];

path = [bundle pathForResource:@"readme" ofType:"txt"];

but if the resource is on the main program I have to use [NSBundle mainBundle] instead.

This is creating a very complex logic because I may have more than one subproject and I will have to create zillions of variations.

Is there a way to make a way the app can find the resource whatever it is using a simple syntax or am I missing something?

Duck
  • 34,902
  • 47
  • 248
  • 470

1 Answers1

0

Factor your resource accesses into a separate class. For example, something like this might work for you:

@interface CSResourceManager

+ (NSString *)pathForResource:(NSString *)resource ofType:(NSString *)type;

@end

@implementation CSResourceManager

+ (NSArray *)resourceBundles
{
    NSBundle *mainBundle = [NSBundle mainBundle];

    NSURL *libraryBundleURL = [mainBundle URLForResource:@"MyLibraryBundle" withExtension:@"bundle"];
    NSBundle *libraryBundle = [NSBundle bundleWithURL:libraryBundleURL];

    // Add more bundles here and/or cache as necessary
    return @[ libraryBundle, mainBundle ];
}

+ (NSString *)pathForResource:(NSString *)resource ofType:(NSString *)type
{
    NSString *path = nil;
    for (NSBundle *bundle in [self resourceBundles]) {
        if ((path = [[self resourceBundle] pathForResource:resource ofType:type])) {
            break;
        }
    }
    return path;
}

@end

If locating the resource bundle every time is too slow, you may want to cache it, i.e. using a static variable.

To use this, you would now just have to write:

NSString *path = [CSResourceManager pathForResource:@"readme" ofType:@"txt"];

In addition to making your code easier to write, using a class like this will also make it easier to maintain (for example, if you want to change the name of the resource bundle, add additional resource storage locations or fallbacks, etc.).

Update #1: see modified code above to support a "search path" of sorts for locating resources.

Update #2: additional ideas for managing resources:

An alternative to using bundles at all would be to have your subprojects share a naming convention for resource files, essentially flattening the namespace. For example, prefix each resource file with the name of the library it's associated with.

Cameron Spickert
  • 5,190
  • 1
  • 27
  • 34
  • Thanks. If I understood this correctly, I am not sure how this solves the problem because I will have to have one method like this for every library with bundle I have and that will be insane. – Duck Apr 09 '13 at 18:08
  • You might have to be more specific about what you're trying to do, then. When you look up a resource, what do you want the behavior to be? How do you decide which library bundle to query? – Cameron Spickert Apr 09 '13 at 18:43
  • This is my problem. I don't want to query any bundle. I may have 3 or more bundles not to mention the main bundle. Every bundle may have to access stuff on the main bundle and vice-versa. What I would like to have is this: "load image wherever it is". I want all bundles to be transparent to the app. – Duck Apr 09 '13 at 18:48
  • See my updated code above. My solution turns bundles into an implementation detail, and allows you to search for resources however/wherever you want. – Cameron Spickert Apr 09 '13 at 18:58
  • Ok, I will accept your code. I think this is an iOS limitation and I don't see another better method of doing this. Thanks! – Duck Apr 09 '13 at 19:10
  • No problem. I've used the above solution successfully in situations like this in the past. Good luck! – Cameron Spickert Apr 09 '13 at 19:14