Question

I'm trying to load a bundle dynamically, to be used in place of the mainBundle in few cases. I managed to load the bundle with some resources, like Localizable.strings and so on. And when I use localizedStringForKey against that bundle, the right localized string is loaded. This is to say that it works.

Nevertheless, I'd like to get even have a bundle identifier. Thus, I added to the root of the bundle folder the info.plist file, containing the CFBundleIdentifier string. This, doesn't work. When I try to get the identifier via

[myBundle bundleIdentifier]

I get a null value. I tried to name the file both as

Info.plist

and

MyBundle-Info.plist

where MyBundle is the name of the bundle (the content is stored in MyBundle.bundle). But no luck.

I really don't get what's wrong. Do I have to set other keys in the info plist? Or maybe it's a naming problem? Any help will be more than appreciated.

Was it helpful?

Solution

I ended up looking at the Core Foundation (after all, NSBundle is based on CFBundle) source code and figured out where was the problem. So..

The function in charge of gathering the info.plist content is CFBundleGetInfoDictionary. This is called anytime an information theoretically contained in the plist is requested.

Looking at CFBundle.c, the implementation of CFBundleGetInfoDictionary checks whether the _infoDict field of the bundle is initialized and in case it's not, it initializes it:

if (!bundle->_infoDict) bundle->_infoDict = _CFBundleCopyInfoDictionaryInDirectoryWithVersion(CFGetAllocator(bundle), bundle->_url, bundle->_version);

By calling that function on my CFBundle I didn't have any luck, so I guessed something wrong must have been happening in _CFBundleCopyInfoDictionaryInDirectoryWithVersion.

Looking at the source code, I noticed that, depending on the bundle->_version, a different path is used to search the info plist. The version in this case depends on the dir structure used to setup the bundle. To be exact, my version was 0, because, as specified in the function _CFBundleURLLooksLikeBundleVersion (used during bundle initialization), bundle with the Resources dir are this:

// check for existence of "Resources" or "Contents" or "Support Files"
    // but check for the most likely one first
    // version 0:  old-style "Resources" bundles
    // version 1:  obsolete "Support Files" bundles
    // version 2:  modern "Contents" bundles
    // version 3:  none of the above (see below)
    // version 4:  not a bundle (for main bundle only)

So, to finish the story, the base URL of the Info.plist is initialized in _CFBundleCopyInfoDictionaryInDirectoryWithVersion based on the version 0

    infoURLFromBase = _CFBundleInfoURLFromBase0;

that is defined as:

#define _CFBundleInfoURLFromBase0 CFSTR("Resources/Info.plist")

Soooo... I've put my Info.plist in the Resources dir and not outside and now it works.

I guess I'm somehow an idiot for having done all this trip, given that this stuff is probably written somewhere in the doc, but I couldn't find it :(

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top