2002-02-01 16:13:20 +00:00
@paragraphindent 0
@node Objective-C
@chapter The Objective-C Language
2004-06-22 22:16:28 +00:00
In the previous chapter you were introduced to some basic object-oriented
programming terms. This chapter will expand on these terms, and introduce you
to some new ones, while concentrating on how they apply to the Objective-C
language and the GNUstep base library. First let us look at some non OO
additions that Objective-C makes to ANSI C.
2002-02-01 16:13:20 +00:00
@section Non OO Additions
Objective-C makes a few non OO additions to the syntax of the C programming
language that include:
@itemize @bullet
@item
A boolean data type (@code{BOOL}) capable of storing either of the
values @code{YES} or @code{NO}.@*
A @code{BOOL} is a scalar value and can be used like the familiar
@code{int} and @code{char} data types.@*
A @code{BOOL} value of @code{NO} is zero, while @code{YES} is non-zero.
@item
The use of a pair of slashes (@code{//}) to mark text up to the end
of the line as a comment.
@item
2004-06-22 22:16:28 +00:00
The @code{#import} preprocessor directive was added; it directs the compiler
to include a file only if it has not previously been included for the current
compilation. This directive should only be used for Objective-C headers and
not ordinary C headers, since the latter may actually rely on being included
more than once in certain cases to support their functionality.
2002-02-01 16:13:20 +00:00
@end itemize
@section Objects
@cindex objects
@c objects
2004-06-22 22:16:28 +00:00
Object-oriented (OO) programming is based on the notion that a software system
can be composed of objects that interact with each other in a manner that
parallels the interaction of objects in the physical world.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
This model makes it easier for the programmer to understand how software works
since it makes programming more intuitive. The use of objects also makes it
easier during program design: take a big problem and consider it in small
pieces, the individual objects, and how they relate to each other.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
Objects are like mini programs that can function on their own when requested
by the program or even another object. An object can receive messages and then
act on these messages to alter the state of itself (the size and position of a
rectangle object in a drawing program for example).
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
In software an object consists of instance variables (data) that represent the
state of the object, and methods (like C functions) that act on these
variables in response to messages.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
As a programmer creating an application or tool, all you need do is send
messages to the appropriate objects rather than call functions that manipulate
data as you would with a procedural program.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
The syntax for sending a message to an object, as shown below, is one of the
additions that Objective-C adds to ANSI C.
2002-02-01 16:13:20 +00:00
@example
[objectName message];
@end example
2004-06-22 22:16:28 +00:00
Note the use of the square [ ] brackets surrounding the name of the object and
message.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
Rather than 'calling' one of its methods, an object is said to 'perform' one
of its methods in response to a message. The format that a message can take is
discussed later in this section.
2002-02-01 16:13:20 +00:00
@subsection Id and nil
2004-06-22 22:16:28 +00:00
Objective-C defines a new type to identify an object: @code{id}, a type that
points to an object's data (its instance variables). The following code
declares the variable '@code{button}' as an object (as opposed to
'@code{button}' being declared an integer, character or some other data type).
2002-02-01 16:13:20 +00:00
@example
id button;
@end example
2004-06-22 22:16:28 +00:00
When the button object is eventually created the variable name '@code{button}'
will point to the object's data, but before it is created the variable could
be assigned a special value to indicate to other code that the object does not
yet exist.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
Objective-C defines a new keyword @code{nil} for this assignment, where
@code{nil} is of type @code{id} with an unassigned value. In the button
example, the assignment could look like this:
2002-02-01 16:13:20 +00:00
@example
id button = nil;
@end example
which assigns @code{nil} in the declaration of the variable.
2004-06-22 22:16:28 +00:00
You can then test the value of an object to determine whether the object
exists, perhaps before sending the object a message. If the test fails, then
the object does not exist and your code can execute an alternative statement.
2002-02-01 16:13:20 +00:00
@example
if (anObject != nil)
... /* send message */
2004-06-22 22:16:28 +00:00
else
... /* do something else */
2002-02-01 16:13:20 +00:00
@end example
2004-06-22 22:16:28 +00:00
The header file @code{objc/objc.h} defines @code{id}, @code{nil}, and other
basic types of the Objective-C language. It is automatically included in your
source code when you use the compiler directive @code{#include
<Foundation/Foundation.h>} to include the GNUstep Base class definitions.
2002-02-01 16:13:20 +00:00
@subsection Messages
@cindex messages
A message in Objective-C is the mechanism by which you pass instructions
to objects. You may tell the object to do something for you, tell it to
change its internal state, or ask it for information.
2004-06-22 22:16:28 +00:00
A message usually invokes a method, causing the receiving object to respond in
some way. Objects and data are manipulated by sending messages to them. Like
C-functions they have return types, but function specific to the object.
2002-02-01 16:13:20 +00:00
Objects respond to messages that make specific requests.
Message expressions are enclosed in square brackets and include the
receiver or object name and the message or method name along with
any arguments.
To send a message to an object, use the syntax:
@code{[receiver messagename];}
where @code{receiver} is the object.
@sp 1
The run-time system invokes object methods that are specified by messages.
For example, to invoke the display method of the mySquare object the
following message is used:
@code{[mySquare display];}
@sp 1
2004-06-22 22:16:28 +00:00
2002-02-01 16:13:20 +00:00
Messages may include arguments that are prefixed by colons, in which
case the colons are part of the message name, so the following message
is used to invoke the @code{setFrameOrigin::} method:
@code{[button setFrameOrigin: 10.0 : 10.0];}
@sp 1
Labels describing arguments precede colons:
@code{[button setWidth: 20.0 height: 122.0];}
2004-06-22 22:16:28 +00:00
2002-02-01 16:13:20 +00:00
invokes the method named @code{setWidth:height:}
@sp 1
2004-06-22 22:16:28 +00:00
2002-02-01 16:13:20 +00:00
Messages that take a variable number of arguments are of the form:
@code{[receiver makeList: list, argOne, argTwo, argThree];}
@sp 1
2004-06-22 22:16:28 +00:00
A message to @code{nil} does NOT crash the application (while in Java messages
to @code{null} raise exceptions); the Objective-C application does nothing.
2002-02-01 16:13:20 +00:00
For example:
@code{[nil display];}
will do nothing.
2004-06-22 22:16:28 +00:00
If a message to @code{nil} is supposed to return an object, it will return
@code{nil}. But if the method is supposed to return a primitive type such as
an @code{int}, then the return value of that method when invoked on
@code{nil}, is undefined. The programmer therefore needs to avoid using the
return value in this instance.
2002-02-01 16:13:20 +00:00
@subsection Polymorphism
@cindex polymorphism
Polymorphism refers to the fact that two different objects may
respond differently to the same message. For example when client
objects receive an alike message from a server object, they may
respond differently. Using Dynamic Binding, the run-time system
determines which code to execute according to the object type.
@section Classes
@cindex classes
2004-06-22 22:16:28 +00:00
A @b{class} in Objective-C is a @i{type of object}, much like a structure
definition in C except that in addition to variables, a class has code --
method implementations -- associated with it. When you create an @i{instance}
of a class, also known as an @i{object}, memory for each of its variables is
allocated, including a pointer to the class definition itself, which tells the
Objective-C runtime where to find the method code, among other things.
Whenever an object is sent a message, the runtime finds this code and
executes it, using the variable values that are set for this object.
2002-02-01 16:13:20 +00:00
@subsection Inheritance
@cindex inheritance
Most of the programmer's time is spent defining classes.
Inheritance helps reduce coding time by providing a convenient way of
reusing code.
2004-06-22 22:16:28 +00:00
For example, the @code{NSButton} class defines data (or instance variables) and methods to create button objects of a certain type, so a subclass of @code{NSButton} could be produced to create buttons of another type - which may perhaps have a different border colour. Equally @code{NSTextField} can be used to define a subclass that perhaps draws a different border, by reusing definitions and data in the superclass.
Inheritance places all classes in a logical hierarchy or tree structure that
may have the @code{NSObject} class at its root. (The root object may be
changed by the developer; in GNUstep it is @code{NSObject}, but in ``plain''
Objective-C it is a class called ``@code{Object}'' supplied with the runtime.)
All classes may have subclasses, and all except the root class do have
superclasses. When a class object creates a new instance, the new object holds
the data for its class, superclass, and superclasses extending to the root
class (typically @code{NSObject}). Additional data may be added to classes so
as to provide specific functions and application logic.
When a new object is created, it is allocated memory space and its data in the
form of its instance variables are initialised. Every object has at least one
instance variable (inherited from @code{NSObject}) called @code{isa}, which is
initialized to refer to the object's class. Through this reference, access is
also afforded to classes in the object's inheritance path.
In terms of source code, an Objective-C class definition has an:
2002-02-01 16:13:20 +00:00
@itemize @bullet
@item
2004-06-22 22:16:28 +00:00
@i{interface} declaring instance variables, methods and the superclass name;
and an
2002-02-01 16:13:20 +00:00
@item
2004-06-22 22:16:28 +00:00
@i{implementation} that defines the class in terms of operational code that
2002-02-01 16:13:20 +00:00
implements the methods.
@end itemize
Typically these entities are confined to separate files
2004-06-22 22:16:28 +00:00
with @code{.h} and @code{.m} extensions for Interface and Implementation files,
2002-02-01 16:13:20 +00:00
respectively. However they may be merged
into one file, and a single file may implement multiple classes.
@subsection Inheritance of Methods
@cindex inheriting methods
Each new class inherits methods and instance variables from another class. This
results in a class hierarchy with the root class at the core, and every class
(except the root) has a superclass as its parent, and all classes may have
numerous subclasses as their children. Each class therefore is a refinement of
its superclass(es).
@subsection Overriding Methods
@cindex overriding methods
Objects may access methods defined for their class, superclass,
superclass' superclass, extending to the root class.
Classes may be defined with methods that overwrite their namesakes
in ancestor classes. These new methods are then inherited by
subclasses, but other methods in the new class can locate the
overridden methods. Additionally redefined methods may include
overridden methods.
@subsection Abstract Classes
@cindex abstract class
@cindex class, abstract
2004-06-22 22:16:28 +00:00
Abstract classes or abstract superclasses such as @code{NSObject} define
2002-02-01 16:13:20 +00:00
methods and instance variables used by multiple subclasses.
Their purpose is to reduce the development effort required to
create subclasses and application structures.
When we get technical, we make a distinction between a pure abstract
class whose methods are defined but instance variables are not,
and a semi-abstract class where instance variables are defined).
2004-06-22 22:16:28 +00:00
2002-02-01 16:13:20 +00:00
An abstract class is not expected to actually produce functional
instances since crucial parts of the code are expected to be
2004-06-22 22:16:28 +00:00
provided by subclasses. In practice, abstract classes may either stub out key
methods with no-op implementations, or leave them unimplemented entirely. In
the latter case, the compiler will produce a warning (but not an error).
2002-02-01 16:13:20 +00:00
Abstract classes reduce the development effort required to create
subclasses and application structures.
@subsection Class Clusters
@cindex class cluster
@cindex cluster, classes
A class cluster is an abstract base class, and a group of private, concrete
subclasses. It is used to hide implementation details from the programmer
2004-06-22 22:16:28 +00:00
(who is only allowed to use the interface provided by the abstract class), so
that the actual design can be modified (probably optimised) at a later date,
without breaking any code that uses the cluster.
Consider a scenario where it is necessary to create a class hierarchy to
define objects holding different types including @b{chars}, @b{ints},
@b{shorts}, @b{longs}, @b{floats} and @b{doubles}. Of course, different types
could be defined in the same class since it is possible to @b{cast} or
@b{change} them from one to the next. Their allocated storage differs,
however, so it would be inefficient to bundle them in the same class and to
convert them in this way.
2002-02-01 16:13:20 +00:00
The solution to this problem is to use a class cluster:
define an abstract superclass that specifies and declares
components for subclasses, but does not declare instance variables.
Rather this declaration is left to its subclasses, which share the
@b{programmatic interface} that is declared by the abstract superclass.
When you create an object using a cluster interface, you are
given an object of another class - from a concrete class in the cluster.
@section NSObject: The Root Class
@cindex NSObject
@cindex root class
@cindex class, root
2004-06-22 22:16:28 +00:00
In GNUstep, @code{NSObject} is a root class that provides a base
implementation for all objects, their interactions, and their integration in
the run-time system. @code{NSObject} defines the @code{isa} instance variable
that connects every object with its class.
In other Objective-C environments besides GNUstep, @code{NSObject} will be
replaced by a different class. In many cases this will be a default class
provided with the Objective-C runtime. In the GNU runtime for example, the
base class is called @code{Object}. Usually base classes define a similar set
of methods to what is described here for @code{NSObject}, however there are
variations.
The most basic functions associated with the @code{NSObject} class (and
inherited by all subclasses) are the following:
2002-02-01 16:13:20 +00:00
@itemize @bullet
@item
2004-06-22 22:16:28 +00:00
allocate instances
2002-02-01 16:13:20 +00:00
@item
2004-06-22 22:16:28 +00:00
connect instances to their classes
2002-02-01 16:13:20 +00:00
@end itemize
2004-06-22 22:16:28 +00:00
In addition, @code{NSObject} supports the following functionality:
2002-02-01 16:13:20 +00:00
@itemize @bullet
@item
2004-06-22 22:16:28 +00:00
initialize instances
2002-02-01 16:13:20 +00:00
@item
2004-06-22 22:16:28 +00:00
deallocate instances
2002-02-01 16:13:20 +00:00
@item
2004-06-22 22:16:28 +00:00
compare self with another object
2002-02-01 16:13:20 +00:00
@item
2004-06-22 22:16:28 +00:00
archive self
2002-02-01 16:13:20 +00:00
@item
2004-06-22 22:16:28 +00:00
perform methods selected at run-time
2002-02-01 16:13:20 +00:00
@item
2004-06-22 22:16:28 +00:00
provide reflective information at runtime to queries about declared methods
2002-02-01 16:13:20 +00:00
@item
2004-06-22 22:16:28 +00:00
provide reflective information at runtime to queries about position in the
inheritance hierarchy
2002-02-01 16:13:20 +00:00
@item
2004-06-22 22:16:28 +00:00
forward messages to other objects.
2002-02-01 16:13:20 +00:00
@end itemize
2004-06-22 22:16:28 +00:00
@subsection The NSObject Protocol
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
In fact, the @code{NSObject} class is a bit more complicated than just
described. In reality, its method declarations are split into two components:
essential and ancillary. The essential methods are those that are needed by
@i{any} root class in the GNUstep/Objective-C environment. They are declared
in an ``@code{NSObject} protocol'' which should be implemented by any other
root class you define (see @ref{Classes, ,Protocols}). The ancillary
methods are those specific to the @code{NSObject} class itself but need not be
implemented by any other root class. It is not important to know which
methods are of which type unless you actually intend to write an alternative
root class, something that is rarely done.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@section Static Typing
@cindex static typing
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
Recall that the @code{id} type may be used to refer to any class of object.
While this provides for great runtime flexibility (so that, for example, a
generic @code{List} class may contain objcts of any instance), it prevents the
compiler from checking whether objects implement the messages you send them.
To allow type checking to take place, Objective-C therefore also allows you to
use class names as variable types in code. In the following example, type
checking verifies that the @code{myString} object is an appropriate type.
2002-02-01 16:13:20 +00:00
@example
2004-06-22 22:16:28 +00:00
// compiler verifies, if anObject's type is known, that it is an NSString:
2002-02-01 16:13:20 +00:00
NSString *myString = anObject;
2004-06-22 22:16:28 +00:00
// now, compiler verifies that NSString declares an int 'length' method:
int len = [myString length];
2002-02-01 16:13:20 +00:00
@end example
2004-06-22 22:16:28 +00:00
Note that objects are declared as pointers, unlike when @code{id} is used.
This is because the pointer operator is implicit for @code{id}. Also, when
the compiler performs type checking, a subclass is always permissible where
any ancestor class is expected, but not vice-versa.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@subsection Type Introspection
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
Static typing is not always appropriate. For example, you may wish to store
objects of multiple types within a list or other container structure. In
these situations, you can still perform type-checking manually if you need to
send an untyped object a particular message. The @code{isMemberOfClass:}
method defined in the @code{NSObject} class verifies that the receiver is of a
specific class:
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@example
if ([namedObject isMemberOfClass: specificClass] == YES)
@{
// code here
@}
2002-02-01 16:13:20 +00:00
@end example
2004-06-22 22:16:28 +00:00
The test will return false if the object is a member of a subclass of the
specific class given - an exact match is required. If you are merely
interested in whether a given object @i{descends} from a particular class, the
@code{isKindOfClass:} method can be used instead:
2002-02-01 16:13:20 +00:00
@example
2004-06-22 22:16:28 +00:00
if ([namedObject isKindOfClass: specificClass] == YES)
@{
// code here
@}
@end example
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
There are other ways of determining whether an object responds to a particular
method, as will be discussed in @ref{Advanced Messaging}.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@subsection Referring to Instance Variables
@cindex instance variables, referring to
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
As you will see later, classes may define some or all of their instance
variables to be @i{public} if they wish. This means that any other object or
code block can access them using the standard ``@code{->}'' structure access
operator from C. For this to work, the object must be statically typed (not
referred to by an @code{id} variable).
2002-02-01 16:13:20 +00:00
@example
2004-06-22 22:16:28 +00:00
Bar *bar = [foo getBar];
int c = bar->value * 2; // 'value' is an instance variable
2002-02-01 16:13:20 +00:00
@end example
2004-06-22 22:16:28 +00:00
In general, direct instance variable access from outside of a class is not
recommended programming practice, aside from in exceptional cases where
performance is at a premium. Instead, you should define special methods
called @i{accessors} that provide the ability to retrieve or set instance
variables if necessary:
2002-02-01 16:13:20 +00:00
@example
2004-06-22 22:16:28 +00:00
- (int) value
@{
return value;
@}
- (void) setValue: (int) newValue
2002-02-01 16:13:20 +00:00
@{
2004-06-22 22:16:28 +00:00
value = newValue;
2002-02-01 16:13:20 +00:00
@}
@end example
2004-06-22 22:16:28 +00:00
While it is not shown here, accessors may perform arbitrary operations before
returning or setting internal variable values, and there need not even be a
direct correspondence between the two. Using accessor methods consistently
allows this to take place when necessary for implementation reasons without
external code being aware of it. This property of @i{encapsulation} makes
large code bases easier to maintain.
2002-02-01 16:13:20 +00:00
@section Working with Class Objects
2004-06-22 22:16:28 +00:00
Classes themselves are maintained internally as objects in their own right in
Objective-C, however they do not possess the instance variables defined by the
classes they represent, and they cannot be created or destroyed by user code.
They do respond to class methods, as in the following:
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@example
id result = [SomeClassName doSomething];
@end example
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
Classes respond to the class methods their class defines, as well as those
defined by their superclasses. However, it is not allowed to override an
inherited class method.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
You may obtain the class object corresponding to an instance object at runtime
by a method call; the class object is an instance of the ``@code{Class}''
class.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@example
// all of these assign the same value
id stringClass1 = [stringObject class];
Class stringClass2 = [stringObject class];
id stringClass3 = [NSString class];
@end example
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
Classes may also define a version number (by overriding that defined in
@code{NSObject}):
2002-02-01 16:13:20 +00:00
@code{int versionNumber = [NSString version];}
2004-06-22 22:16:28 +00:00
This facility allows developers to access the benefits of versioning for
classes if they so choose.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@subsection Locating Classes Dynamically
Class names are about the only names with global visibility in Objective-C.
If a class name is unknown at compilation but is available as a string at run
time, the GNUstep library @code{NSClassFromString} function may be used to
return the class object:
2002-02-01 16:13:20 +00:00
@example
2004-06-22 22:16:28 +00:00
if ([anObject isKindOf: NSClassFromString("SomeClassName")] == YES)
@{
// do something ...
@}
2002-02-01 16:13:20 +00:00
@end example
2004-06-22 22:16:28 +00:00
The function returns @code{Nil} if it is passed a string holding an invalid
class name. Class names, global variables and functions (but not methods)
exist in the same name space, so no two of these entities may share the same
name.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@section Naming Constraints and Conventions
@cindex naming constraints
@cindex naming conventions
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
The following lists the full uniqueness constraints on names in Objective-C.
@itemize @bullet
@item
Neither gGlobal variables nor function names may share the same name as
classes, because all three entities are allocated the same (global) name
space.
@item
A class may define methods using the same names as those held in other classes.
(See @ref{Objective-C, ,Overriding Methods} above.)
@item
A class may define instance variables using the same names as those
held in other classes.
@item
A class category may have the same name as another class category.
@item
An instance method and a class method may share the same name.
@item
A protocol may have the same name as a class, category, or any other entity.
@item
A method and an instance variable may share the same name.
@end itemize
There are also a number of conventions used in practice. These help to make
code more readable and also help avoid naming conflicts. Conventions are
particularly important since Objective-C does not have any namespace
partitioning facilities like Java or other languages.
@itemize @bullet
@item
Class, category and protocol names begin with an uppercase letter.
@item
Methods, instance variables, and variables holding instances begin
with a lowercase letter.
@item
Second and subsequent words in a name should begin with a capital letter, as
in ``ThisIsALongName'', not ``Thisisalongname''. As can be seen, this makes
long names more readable.
@item
Classes intended to be used as libraries (Frameworks, in NeXTstep parlance)
should utilize a unique two or three letter prefix. For example, the
Foundation classes all begin with 'NS', as in ``NSArray, and classes in the
OmniFoundation from Omni Group (a popular library for OpenStep) began with
``OF''.
@item
Classes and methods intended to be used only be the developers maintaining
them should be prefixed by an underscore, as in ``_SomePrivateClass'' or
``_somePrivateMethod''. Capitalization rules should still be followed.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@item
Functions intended for global use should beging with a capital letter, and
use prefixing conventions as for classes.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@end itemize
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@ignore
@subsection Pitfalls of Using Class Names
2002-02-01 16:13:20 +00:00
(To be completed.)
2004-06-22 22:16:28 +00:00
@end ignore
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@section Strings in GNUstep
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
Strings in GNUstep can be handled in one of two ways. The first way is the C
approach of using an array of @code{char}. In this case you may use the
``@code{STR}'' type defined in Objective-C in place of @code{char[]}.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
The second approach is to rely on the @code{NSString} class and associated
subclasses in the GNUstep Base library, and compiler support for them. Using
this approach allows use of the methods in the
@uref{../Reference/NSString.html, NSString API}. In addition, the
@code{NSString} class provides the means to initialize strings using
printf-like formats.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
The @code{NSString} class defines objects holding raw @b{Unicode} character
streams or @b{strings}. Unicode is a 16-bit worldwide standard used to define
character sets for all spoken languages. In GNUstep parlance the Unicode
character is of type @b{unichar}.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@subsection Creating NSString Static Instances
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
A @b{static} instance is allocated at compile time. The creation of a static
instance of @code{NSString} is achieved using the @code{@@"..."} construct
and a pointer:
2002-02-01 16:13:20 +00:00
@example
2004-06-22 22:16:28 +00:00
NSString *w = @@"Brainstorm";
2002-02-01 16:13:20 +00:00
@end example
2004-06-22 22:16:28 +00:00
Here, @code{w} is a variable that refers to an @code{NSString} object
representing the ASCII string "Brainstorm".
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@subsection NSString +stringWithFormat:
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
The class method @code{stringWithFormat:} may also be used to create instances
of @code{NSString}, and broadly echoes the @code{printf()} function in the C
programming language. @code{stringWithFormat:} accepts a list of arguments
whose processed result is placed in an @code{NSString} that becomes a return
value as illustrated below:
2002-02-01 16:13:20 +00:00
@example
2004-06-22 22:16:28 +00:00
int qos = 5;
NSString *gprsChannel;
gprschannel = [NSString stringWithFormat: @@"The GPRS channel is %d",
qos];
2002-02-01 16:13:20 +00:00
@end example
2004-06-22 22:16:28 +00:00
The example will produce an @code{NSString} called @code{gprsChannel}
holding the string "The GPRS channel is 5".
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@code{stringWithFormat:} recognises the @code{%@@} conversion specification
that is used to specify an additional @code{NSString}:
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@example
NSString *one;
NSString *two;
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
one = @@"Brainstorm";
two = [NSString stringWithFormat: @@"Our trading name is %@@", one];
@end example
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
The example assigns the variable @code{two} the string "Our trading name is
Brainstorm." The @code{%@@} specification can be used to output an object's
description - as returned by the @code{NSObject} @code{-description} method),
which is useful when debugging, as in:
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@example
NSObject *obj = [anObject aMethod];
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
NSLog (@@"The method returned: %@@", obj);
@end example
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@subsection C String Conversion
When a program needs to call a C library function it is useful to convert
between @code{NSString}s and standard ASCII C strings (not fixed at compile
time). To create an @code{NSString} using the contents of the returned C
string (from the above example), use the @code{NSString} class method
@code{stringWithCString:}:
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@example
char *function (void);
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
char *result;
NSString *string;
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
result = function ();
string = [NSString stringWithCString: result];
@end example
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
To convert an @code{NSString} to a standard C ASCII string,
use the @code{cString} method of the @code{NSString} class:
@example
char *result;
NSString *string;
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
string = @@"Hi!";
result = [string cString];
@end example
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@subsection NSMutableString
@code{NSString}s are immutable objects; meaning that once they are created,
they cannot be modified. This results in optimised @code{NSString} code. To
modify a string, use the subclass of @code{NSString}, called
@code{NSMutableString}. Use a @code{NSMutableString} wherever a
@code{NSString} could be used.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
An @code{NSMutableString} responds to methods that modify the string directly -
which is not possible with a generic @code{NSString}.
To create a @code{NSMutableString}use @code{stringWithFormat:}:
@example
NSString *name = @@"Brainstorm";
NSMutableString *str;
str = [NSMutableString stringWithFormat: @@"Hi!, %@@", name];
@end example
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
While @code{NSString}'s implementation of @code{stringWithFormat:} returns
a @code{NSString}, @code{NSMutableString}'s implementation returns an
@code{NSMutableString}.
2002-02-01 16:13:20 +00:00
2004-06-22 22:16:28 +00:00
@b{Note. Static strings created with the @code{@@"..."} construct are
always immutable.}
@code{NSMutableString}s are rarely used because to modify a string, you
normally create a new string derived from an existing one.
A useful method of the @code{NSMutableString} class is @code{appendString:},
which takes an @code{NSString} argument, and appends it to the receiver:
2002-02-01 16:13:20 +00:00
@example
2004-06-22 22:16:28 +00:00
NSString *name = @@"Brainstorm";
NSString *greeting = @@"Hello";
NSMutableString *s;
s = AUTORELEASE ([NSMutableString new]);
[s appendString: greeting];
[s appendString: @@", "];
[s appendString: name];
@end example
This code produces the same result as:
@example
NSString *name = @@"Brainstorm";
NSString *greeting = @@"Hello";
NSMutableString *s;
s = [NSMutableString stringWithFormat: @@"%@@, %@@", greeting, name];
@end example
@subsection Loading and Saving Strings
The the GNUstep Base library has numerous string manipulation features,
and among the most notable are those relating to writing/reading
strings to/from files. To write the contents of a string to a file,
use the @code{writeToFile:atomically:} method:
@example
#include <Foundation/Foundation.h>
int
main (void)
@{
CREATE_AUTORELEASE_POOL(pool);
NSString *name = @@"This string was created by GNUstep";
if ([name writeToFile: @@"/home/nico/testing" atomically: YES])
@{
NSLog (@@"Success");
@}
else
@{
NSLog (@@"Failure");
@}
RELEASE(pool);
return 0;
@}
@end example
@code{writeToFile:atomically:} returns YES for success, and NO for failure.
If the atomically flag is YES, then the library first writes the string
into a file with a temporary name, and, when the writing has been
successfully done, renames the file to the specified filename.
This prevents erasing the previous version of filename unless
writing has been successful. This is a useful feature, which should be enabled.
To read the contents of a file into a string, use
@code{stringWithContentsOfFile:}, as shown in the following
example that reads @code{@@"/home/Brainstorm/test"}:
@example
#include <Foundation/Foundation.h>
int
main (void)
@{
CREATE_AUTORELEASE_POOL(pool);
NSString *string;
NSString *filename = @@"/home/nico/test";
string = [NSString stringWithContentsOfFile: filename];
if (string == nil)
@{
NSLog (@@"Problem reading file %@@", filename);
/*
* <missing code: do something to manage the error...>
* <exit perhaps ?>
*/
@}
/*
* <missing code: do something with string...>
*/
RELEASE(pool);
return 0;
@}
2002-02-01 16:13:20 +00:00
@end example
@page