CFBundle allows you to use a folder hierarchy called a bundle to organize and locate many types of application resources including images, sounds, localized strings, and executable code. In macOS, bundles can also be used by CFM applications to load and execute functions from Mach-O frameworks. You can use bundles to support multiple languages or execute your application on multiple operating environments.
You create a bundle object using one of the
CFBundleCreate... functions. CFBundle provides several functions for finding resources within a bundle. The
CFBundleCopyResourceURL(_:_:_:_:) function returns the location of a resource of the specified name and type, and in the specified subdirectory. Use
CFBundleCopyResourceURLForLocalization(_:_:_:_:_:) to restrict the search to a specific localization name. Use
CFBundleCopyResourceURLsOfType(_:_:_:) to get the locations of all resources of a specified type.
CFBundle provides functions for getting bundle information, such as its identifier and information dictionary. Use the
CFBundleGetIdentifier(_:) function to get the identifier of a bundle, and the
CFBundleGetInfoDictionary(_:) function to get its information dictionary. The principal intended purpose for locating bundles by identifier is so that code (in frameworks, plugins, etc.) can find its own bundle.
You can also obtain locations of subdirectories in a bundle represented as CFURL objects. The
CFBundleCopyExecutableURL(_:) function returns the location of the application’s executable. The functions
CFBundleCopyBuiltInPlugInsURL(_:) return the location of a bundle’s subdirectory containing resources, shared frameworks, private frameworks, shared support files, and plug-ins respectively.
Other functions are used to manage localizations. The
CFBundleCopyLocalizationsForURL(_:) functions return a localized string from a bundle’s strings file. The
CFBundleCopyLocalizationsForPreferences(_:_:) function returns the localizations that CFBundle would prefer, given the specified bundle and user preference localizations.
Unlike some other Core Foundation opaque types with similar Cocoa Foundation names (such as CFString and
Bundle objects cannot be cast (“toll-free bridged”) to CFBundle objects.
NSBundle, which does not support unloading (because the Objective C runtime does not support the unloading of Objective C code), you can unload CFBundle objects.
CFBundleGetFunctionPointerForName(_:_:) and related calls automatically load a bundle if it is not already loaded. When the last reference to the CFBundle object is released and it is finally deallocated, then the code will be unloaded if it is still loaded and if the executable is of a type that supports unloading. If you keep this in mind, and if you make sure that everything that uses the bundle keeps a retain on the CFBundle object, then you can just use the bundle naturally and never have to worry about when it is loaded and unloaded.
On the other hand, if you want to manually manage when the bundle is loaded and unloaded, then you can use
CFBundleUnloadExecutable(_:)—although this technique is not recommended. These functions force immediate loading and unloading of the executable (if it has not already been loaded/unloaded, and in the case of unloading if the executable is of a type that supports unloading). If you do this, then the code calling
CFBundleUnloadExecutable is responsible for making sure that there are no remaining references to anything in the bundle's code before it is unloaded. In the previous approach, by contrast, this responsibility can be distributed to the individual code sections that use the bundle, by making sure that each one keeps its own retain on the CFBundle object.
One further point about CFBundle reference counting: if you are taking the first approach, but do not actually wish the bundle’s code to be unloaded (as is often the case), or if you are taking the second approach of manually managing the unloading yourself, then in many cases you do not actually have to worry about releasing a CFBundle object. CFBundle instances are uniqued, so there is only one CFBundle object for a given bundle, and rarely are there so many bundles being considered at once that the memory usage for CFBundle objects would be significant. There are cases in which a process could create CFBundle objects for potentially an unlimited number of bundles, and such processes would wish to balance retains and releases carefully, but such cases are likely to be rare.
Note that it is best to compile any unloadable bundles with the flag
-fno-constant-cfstrings—see Bundle Programming Guide for more details.