There are three ways to obtain access to a bundle from a running application. The first method is to simply call the function
CFBundleGetMainBundle
. This function allows an application to reference its main bundle. The main bundle is the bundle that the running program was launched from. Because not all programs that use Core Foundation are packaged in bundles--most command-line tools aren't, for example--it is possible that the main bundle will be
NULL
.
Listing 1 Locating the main bundle
CFBundleRef mainBundle; // Get the main bundle for the app mainBundle = CFBundleGetMainBundle();
The second method for accessing a bundle requires a URL describing the location of the bundle. There are several ways to construct a bundle's URL. If a bundle is packaged as a resource of your main application, you could use CFBundle's resource-finding API to locate the bundle's URL. If your bundle is going to be installed in a standard filesystem location, you could hardcode the file path in your application--as demonstrated in Listing 2--or store it as a key in the
Info.plist
file.
Listing 2 Locating a bundle using its path name
CFURLRef bundleURL; CFBundleRef myBundle; // Make a CFURLRef from the CFString representation of the // bundle's path. See the Core Foundation URL Services chapter // for details. bundleURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, CFSTR("/Local/Library/MyBundle.bundle"), kCFURLPOSIXPathStyle, true ); // Make a bundle instance using the URLRef. myBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL ); // Any CF objects returned from functions with "create" or // "copy" in their names must be released by us! CFRelease( bundleURL ); CFRelease( myBundle );
For bundles stored inside your application's main bundle, the best way to find and open a bundle is to use CFBundle's Resource-finding API. This way you don't have to hard code any pathnames, and can let CFBundle do more work for you. Information on the resource-finding API can be found in the Core Foundation Bundle Services Concepts section as well as in the section Locating Resources Inside a Bundle. Listing 3 demonstrates this approach.
Listing 3 Locating a bundle using the bundle name
#define kBundleAnyType NULL #define KBundleNoSubdir NULL CFBundleRef mainBundle; CFURLRef bundleURL; CFBundleRef myBundle; // Get the main bundle for the app mainBundle = CFBundleGetMainBundle(); // Look for a resource in the main bundle by name bundleURL = CFBundleCopyResourceURL( mainBundle, CFSTR("myBundle.bundle"), kBundleAnyType, KBundleNoSubdir ); // Make a bundle instance using the URLRef myBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL ); // Release the CF objects CFRelease( bundleURL ); CFRelease( myBundle );
In some situations you might want to create instances for all of the bundles found in a given folder. This would be useful for an application that defines a particular folder as the standard location for plug-ins.
Listing 4 Obtaining bundle references for several bundles in a folder
#define kBundleAnyType NULL CFArrayRef bundleArray; CFURLRef pluginDirURL; bundleArray = CFBundleCreateBundlesFromfolder( kCFAllocatorDefault, pluginDirURL, kBundleAnyType );
The third and final method requires that the developer define an identifier for a particular bundle. An identifier can later be used to find the bundle instance. This is useful for executable code that needs to find the resources packaged with it.
For example, suppose an application loads a bundle that consists of some code and some images. The images are resources of the bundle that contains the code. But how can the code in the bundle find the images? The bundle's code cannot know the proper absolute URL because the bundle might have been loaded from anywhere. If the bundle writer gives the bundle an identifier, the code can then use the identifier to find the bundle at runtime and get access to its resources.
You can associate an identifier with a bundle by creating a value for the key
CFBundleIdentifier
in your
CustomInfo.plist
file. Bundle identifiers need to be unique, so be sure to use the package naming conventions (for example,
com.apple.Finder.MyGetInfoPlugin
) to avoid collision with other bundle writers.
Remember that a bundle identifier can only be used to locate an existing CFBundle instance (including the main bundle and bundles for all statically linked frameworks). If your bundle has been opened and its code is running, then you can use the bundle's identifier to find it.
Listing 5 Locating a bundle using its identifier
CFBundleRef requestedBundle; // Look for a bundle using its identifier requestedBundle = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.Finder.MyGetInfoPlugIn") );