An NSBundle is an object that corresponds to a directory where
related resources-including executable code-are stored. The
directory, in essence, "bundles" a set of resources used by
an application into convenient chunks, and the NSBundle object makes
those resources available to the application. NSBundle can find
requested resources in the directory and can dynamically load executable code.
The term bundle refers both to the object and to the directory it
represents.
Bundles are useful in a variety of contexts. Since bundles
combine executable code with the resources used by that code, they
facilitate installation and localization. NSBundles are also used
to locate specific resources, to obtain localized strings, to load
code dynamically, and to determine which classes are loaded.
Each resource in a bundle usually resides in its own file.
Bundled resources include such things as:
The Project Builder application defines four types of projects
that build bundles as file packages. A file package is a directory
that the Workspace Manager presents to users as if it were a simple
file; the contents of the directory are hidden. The four types of
Project Builder bundles are:
For all types of bundles, the executable-code file of a bundle
(of which there can be only one) is in the immediate bundle directory
and takes the same name as the bundle, minus the extension. Bundles
also encode (as a property list) the important attributes of the
bundle, such as the main nib file name, executable name, document
extensions, and so forth. You can access these attributes with NSBundle's infoDictionary method,
which returns the file's contents as an NSDictionary.
Every application has at least one bundle-its main bundle-which
is the ".app" directory where its executable file is located.
This file is loaded into memory when the application is launched.
It includes at least the main()
function
and other code necessary to start up the application. You obtain
an NSBundle object corresponding to the main bundle with the class
method mainBundle.
Frameworks are bundles that package dynamic shared libraries
along with the nib files, images, and other resources that support
the executable code and with the header files and documentation
that describe the associated APIs. As long as your applications
are dynamically linked with frameworks, you should have little need
to do anything explicitly with those frameworks thereafter; in a
running application, the framework code is automatically loaded,
as needed. You can however, get an NSBundle object associated with
a framework by invoking the class method bundleForClass specifying, as the
argument, a class that's defined in the framework.
An application can be organized into any number of other bundles
in addition to the main bundle and the bundles of linked-in frameworks.
Although these loadable bundles usually reside inside the application
file package, they can be located anywhere in the file system. Each
loadable-bundle directory-by convention, with a ".bundle"
extension-is represented in the application by a separate NSBundle
object. Through this object the application can dynamically load
the code and resources in the bundle when it needs them. For example,
an application for managing PostScript printers may have a bundle
full of PostScript code to be downloaded to printers.
The executable code files in loadable bundles hold class (and
category) definitions that the NSBundle object can dynamically load
while the application runs. When asked for a certain class (through
the invocation of classNamed: or principalClass),
the NSBundle loads the object file that contains the class definition
(if it's not already loaded) and returns the class object; it
also loads other classes and categories that are stored in the file.
The major advantage of bundles is application extensibility.
A set of bundled classes often supports a small collection of objects
that can be integrated into the larger object network already in
place. (Preferences is one example of this.) The linkage is established
through an instance of the principal class. This object might have
methods to return other objects that the application can talk to,
but typically all messages from the application to the subnetwork
are funneled through the one instance.
Since each bundle can have only one executable file, that
file should be kept free of localizable content. Anything that needs
to be localized should be segregated into separate resource files
and stored in localized-resource subdirectories.
To create a loadable
bundle-a bundle with dynamically loadable code-without using
Project Builder, use the ld(1) -bundle flag on the cc command line. |
Localized Resources
If an application is to be used in more than one part of the
world, its resources may need to be customized, or "localized,"
for language, country, or cultural region. An application may need,
for example, to have separate Japanese, English, French, Hindu,
and Swedish versions of the character strings that label menu commands.
Resource files specific to a particular language are grouped
together in a subdirectory of the bundle directory. The subdirectory
has the name of the language (in English) followed by a ".lproj"
extension (for "language project"). The application mentioned
above, for example, would have Japanese.lproj
, English.lproj
, French.lproj
, Hindi.lproj
,
and Swedish.lproj
subdirectories.
Each ".lproj" subdirectory in a bundle has the same set of files;
all versions of a resource file must have the same name. Thus, Hello.snd
in French.lproj
should
be the French counterpart to the Swedish Hello.snd
in Swedish.lproj
,
and so on. If a resource doesn't need to be localized at all,
it's stored in the bundle directory itself, not in the ".lproj"
subdirectories.
The user determines which set of localized resources will
actually be used by the application. NSBundle objects rely on the
language preferences set by the user in the Preferences application.
Preferences lets users order a list of available languages so that
the most preferred language is first, the second most preferred language
is second, and so on.
When an NSBundle is asked for a resource file, it provides
the path to the resource that best matches the user's language
preferences. For details, see the description of pathForResource.
How NSBundles Locate Resources
A bundle's resources are typically stored in a directory named Resources
within the
bundle directory. Within the Resources
directory
are non-localized resources and localized resource directories (English.lproj
, Swedish.lproj
,
and so on). Generally, when an NSBundle looks for resources, it
starts at the top, in a non-localized location, and searches "downward"
toward the localized directories.
For example, suppose you want to find a resource with name
"Main" and type "nib". NSBundle searches the Resource directory
at the "top" non-localized level for the file Main.nib
.
If it doesn't find the file there, NSBundle then searches each of
the language subdirectories in the user's preferred order of languages.
By this scheme, the localized version of a resource that also exists
at the top level will not be found, but the non-localized one will
be. For this reason, you should place all non-localized resources
in the top level of Resources, and you shouldn't put any localized
resources there.
When it finds a resource, an NSBundle checks if a resource
of the name Main-$(PLATFORM_OS)
of
type "nib" exists. $(PLATFORM_OS)
represents
the make variable of the same name, and takes on the same values
that the make variable takes on at compile time. For example, on
Windows, during a project build, $(PLATFORM_OS)
in
the Makefile.postamble will yield the value
"winnt". When Main.nib
is
found in a directory, the NSBundle also sees if Main-winnt.nib
exists
in that same directory. If it does, the NSBundle returns the path
to the platform-specific resource; if it does not, it returns the
path to Main.nib
. Note
that for Main-winnt.nib
to
be found, a file named Main.nib
must
exist in the same directory (including language-specific resource
directories). You typically give one platform-general version of
a resource the name without this $(PLATFORM_OS)
suffix,
and give the platform-specific versions of the resource extended
names. The values that $(PLATFORM_OS)
can
take are currently "winnt" (on OPENSTEP for Windows),
"nextstep" (on OPENSTEP for MACH), "hpux"(on
PDO for HP-UX), and "solaris" (on PDO for Solaris).
Another way to accommodate platform-specific resources is
to use the bundlePath parameter of
NSBundle's resource-searching methods. The bundlePath parameter
is intended for locating resources of a common type or purpose that
are put in a single directory; for example, all images could be
put into a directory called Images
within
the Resource
directory.
(However, note that the Application Kit's imageNamed: class
method in NSImage does not support searching arbitrary directories
for images.) You can thus use specialized resource subdirectories
and the bundlePath parameter to manage
platform-specific resources. This is not "automatic" functionality,
however, since it requires the developer to specify the name of
the platform-specific directory as well as replicate the required
resources and language projects within that directory. The $(PLATFORM_OS)
mechanism
is simpler to use, particularly if the number of platform-specific
resources is small.
Method Types
- Getting an NSBundle
- bundleForClass
- bundleWithPath
- mainBundle
- allBundles
- allFrameworks
- Getting a bundled class
- principalClass
- Finding a resource
- pathsForResources
- resourcePath
- Getting the bundle directory
- bundlePath
- Getting bundle information
- infoDictionary
- Managing localized resources
- localizedStringForKey
- Loading a bundle's
code
- load
Constructors
NSBundle
public NSBundle(String aString)
<<Documentation Forthcoming>>
Static
Methods
public static NSArray allBundles()
Returns an array of all the
application's non-framework bundles. This includes the
main bundle and all bundles that have been dynamically created but
doesn't contain any bundles that represent frameworks.
public static NSArray allFrameworks()
Returns an array of all of
the application's bundles that represent frameworks. This
includes frameworks which are linked into an application when the application
is built and bundles for frameworks which have been dynamically created.
public static NSBundle bundleForClass(Class aClass)
Returns the NSBundle that dynamically
loaded aClass (a loadable bundle),
the NSBundle for the framework in which aClass is
defined, or the main bundle object if aClass was
not dynamically loaded or is not defined in a framework.See
Also: mainBundle, bundleWithPath
public static NSBundle bundleWithPath(String path)
Returns an NSBundle that corresponds
to the specified directory path or null
if path does
not identify an accessible bundle directory. This
method allocates and initializes the returned object if it doesn't
already exist. See Also: mainBundle, bundleForClass
localizedString
public static String localizedString(String aString)
<<Documentation Forthcoming>>
public static String localizedString(String aString, String aString)
<<Documentation Forthcoming>>
public static String localizedString(String aString, String aString, String aString)
<<Documentation Forthcoming>>
public static String localizedString(String aString, String aString, NSBundle aBundle, String aString)
<<Documentation Forthcoming>>
public static NSBundle mainBundle()
Returns an NSBundle that corresponds
to the directory where the application executable is located or null
if
this executable is not located in an accessible bundle directory. This
method allocates and initializes the returned NSBundle if it doesn't
already exist.In general, the main bundle corresponds to an
application file package or application wrapper: a directory that
bears the name of the application and is marked by a ".app"
extension.
See Also: bundleForClass, bundleWithPath
Instance Methods
public String bundlePath()
Returns the full pathname of
the receiver's bundle directory.
public NSDictionary infoDictionary()
Returns a dictionary that contains information
about the receiver. This information is extracted from the property
list (Info.plist) associated with the bundle. The returned dictionary
is empty if no Info.plist can be found. Common keys for accessing
the values of the dictionary are NSExecutable, NSExtensions, NSIcon,
NSMainNibFile, and NSPrincipalClass. See
Also: principalClass
public boolean load()
Dynamically loads the bundle's
executable code into a running program, if the code has not already
been loaded. A bundle attempts to load its code-if
it has any-only once. Returns true
if
the method successfully loaded the bundle's code or if the code
had already been loaded. Returns false
if
the method failed to load the code.You don't need to load a bundle's
executable code to search the bundle's resources.See
Also: classNamed:principalClass
public String localizedStringForKey(String key, String value, String tableName)
Returns a localized version
of the string designated by key in
table tableName. The
argument tableName specifies the
receiver's string table to search. If tableName is null
or
is an empty string, the method attempts to use the table in Localizable.strings.
The value argument specifies the
value to return if key is null or
if a localized string for key can't
be found in the table. If value is null
or
an empty string, and a localized string is not found in the table,
the method returns key. If key and value are
both null
, the method returns the
empty string.Using the user default NSShowNonLocalizedStrings,
you can alter the behavior of localizedStringForKey to log a message
when the method can't find a localized string. If you set this
default to true
(in the global domain
or in the application's domain), then when the method can't
find a localized string in the table, it logs a message to the console
and capitalizes key before returning
it.
See Also: pathForResource:ofType:pathForResource:ofType:inDirectory:pathForResource:ofType:inDirectory:pathsForResources
pathForResource
public String pathForResource(String name, String extension)
Returns the full pathname for
the resource identified by name with
the specified file extension. If the extension argument
is null
or an empty string (@""),
the resource sought is identified by name,
with no extension. The method first looks for a non-localized resource
in the immediate bundle directory; if the resource is not there,
it looks for the resource in the language-specific ".lproj"
directory (the local language is determined by user defaults).
public String pathForResource(String name, String extension, String bundlePath)
Returns the full pathname for
the resource identified by name,
with the specified file name extension, and residing in the directory bundlePath;
returns null
if no matching resource
file exists in the bundle. The argument bundlePath must
be a valid bundle directory or null. The
argument extension can be an empty
string or null
; in either case the
pathname returned is the first one encountered with name,
regardless of the extension. The method searches in this order:
<main bundle path>/Resources/
bundlePath/name.
extension
<main bundle path>/Resources/
bundlePath/<language.lproj>/
name.extension
<main bundle path>/bundlePath/
name.extension
<main bundle path>/bundlePath/<language.lproj>/
name.extension
The
order of language directories searched corresponds to the user's
preferences. If bundlePath is null
,
the same search order as described above is followed, minus bundlePath.
See
Also: localizedStringForKey, pathsForResources
public NSArray pathsForResources(String extension, String bundlePath)
Returns an array containing
pathnames for all bundle resources having the specified file name
extension and residing in the directory bundlePath;
returns an empty array if no matching resource files are found. This
method provides a means for dynamically discovering bundle resources.
The argument bundlePath must be a
valid bundle directory or null. The extension argument
can be an empty string or null
; if
you specify either of these for extension,
all bundle resources are returned. Although there is no guaranteed
search order, all of the following directories will be searched:
<main bundle path>/Resources/
bundlePath/name.
extension
<main bundle path>/Resources/
bundlePath/<language.lproj>/
name.extension
<main bundle path>/bundlePath/
name.extension
<main bundle path>/bundlePath/<language.lproj>/
name.extension
The
language directories searched corresponds to the user's preferences.
If bundlePath is null,
the same search order as described above is followed, minus bundlePath.
See
Also: pathForResource:ofType:pathForResource:ofType:inDirectory:pathForResource:ofType:inDirectory:localizedStringForKey
public Class principalClass()
Returns the NSBundle's principal
class after ensuring that the code containing the definition of
that class is dynamically loaded. If the NSBundle
encounters errors in loading or if it can't find the executable
code file in the bundle directory, it returns null
.
The principal class typically controls all the other classes in
the bundle; it should mediate between those classes and classes
external to the bundle. Classes (and categories) are loaded from
just one file within the bundle directory. NSBundle obtains the
name of the code file to load from the dictionary returned from infoDictionary,
using "NSExecutable" as the key. The NSBundle determines its
principal class in one of two ways:- It first looks
in its own information dictionary, which extracts the information encoded
in the bundle's property list (Info.plist). NSBundle obtains the principal
class from the dictionary using the key NSPrincipalClass. For non-loadable
bundles (applications and frameworks), if the principal class is not
specified in the property list, the method returns nil.
- If the principal class is not specified in the information
dictionary, NSBundle identifies the first class loaded as the principal
class. When several classes are linked into a dynamically loadable
file, the default principal class is the first one listed on the ld command
line. In the following example, Reporter would be the principal
class:
ld -o
myBundle -r Reporter.o NotePad.o QueryList.o
The order of classes in Project
Builder's project browser is the order in which they will be linked.
To designate the principal class, Control-drag the file containing
its implementation to the top of the list.
As a side-effect
of code loading, the receiver posts NSBundleDidLoadNotification after
all classes and categories have been loaded; see "Notifications,"
below for details.
See Also: classNamed:infoDictionary, load
public String resourcePath()
Returns the full pathname of the receiving bundle's
subdirectory containing resources.See Also: bundlePath
Notifications
The following notification is declared and posted by NSBundle.
NSBundleDidLoadNotification
This notification contains a notification object and a userInfo
dictionary. The notification object is the NSBundle that dynamically
loads classes. The userInfo dictionary
contains these keys and values:
Key |
Value |
NSLoadedClasses |
An NSArray containing the names (as NSStrings) of each
class and category that was loaded |
NSBundle posts NSBundleDidLoadNotification to notify observers
which classes and categories have been dynamically loaded. When
a request is made to an NSBundle for a class (classNamed: or principalClass), the bundle dynamically
loads the executable code file that contain the class implementation and
all other class definitions contained in the file. After the module
is loaded, the NSBundle posts a notification with a userInfo dictionary
containing all classes that were loaded.
In a typical use of this notification, an object might want
to enumerate the userInfo NSArray
to check if each loaded class conformed to a certain protocol (say,
a protocol for a plug-and-play tool set); if a class does conform,
the object would create an instance of that class and add the instance
to another NSArray.
[Previous] [Next]