Root Classes

A root class is one with no parent class. Objective-C allows multiple root classes, but you are most likely to use one supplied with your compiler.

All Objective-C distributions provide a root class called Object. This section describes the Object supplied with the GNU runtime. The Object class provided by Darwin is similar, but Darwin users will be more likely to use the NSObject root class that comes with the Cocoa class library. (The GNUstep library also provides an NSObject root class almost identical to Cocoa’s.) This section describes the fields and methods of both Object and NSObject.

Both classes provide access to Objective-C features like reflection, memory management, and archiving. Most of the classes you write will inherit from one of these classes, so your objects will be able to use these features.

Note

The runtime goes to some length to make class objects behave the same as regular objects. In particular, they appear to inherit their fields and methods from the root classes, so they share in the properties described in this section.

Fields

Both Object and NSObject declare only one field, isa , whose type is Class. This field is inherited by all their descendants, which is critical to the operation of inheritance and message dispatch. It points to the class object representing the instance’s class. See Section 1.9 earlier in this book.

Methods

Root class methods are accessible from any object that derives from the class—usually all regular objects in a program. In addition, root class instance methods can be called on class objects for it and its subclasses—in other words, class objects appear to be instances of their root class. (The runtime arranges for this; see Section 1.9.2 under Section 1.9.)

Because you can call root class instance methods on class objects, the behavior of some instance methods described here has several distinct, though consistent, cases:

  • The receiver is a regular object.

  • The receiver is a class object.

  • The receiver is a metaclass object (in the GNU runtime, where metaclass objects are distinguished from class objects).

The root class method descriptions point these issues out where useful.

Some root class methods are meant to be overridden; others should not be. The following sections note where you may or must override a method.

Note

Many root class methods (e.g., -respondsTo:) return information about the receiver even when it’s an instance of a subclass. This makes it look like they are automatically rewritten in each subclass, or that your classes should override them. In fact, the root class’s implementation makes use of runtime reflection to provide the information required.

The Object Class

This section describes the methods provided by the GNU Object class. The source code for these methods, available in Object.m, gives a valuable view of how the Objective-C runtime works.

Creating, copying, and freeing objects

Object provides the following methods to manage the memory used for objects. You should never use the C functions malloc( ) and free( ) to manage Objective-C objects. The earlier Section 1.7 discusses how to use these methods.

+( id )new

Calls +alloc on the class, then -init on the resulting instance, and returns the result.

+( id )alloc

Allocates, clears, and returns a pointer to memory for a new instance of the receiver. Returns nil on failure.

+( id )initialize

Returns self. The runtime calls this method before any instances of the receiving class are created. Override to perform class-specific setup.

-( id )init

Returns self. This is the designated initializer for Object.

-( id )copy

Calls -shallowCopy then -deepen on the resulting instance, and returns the result. In Object this is the same as -shallowCopy.

-( id )shallowCopy

Returns a copy of the receiver. Fields that are pointers are not traversed, just duplicated in the new copy.

-( id )deepen

Returns self. Override to replace all fields that are pointers with new values. Otherwise, -deepCopy and -copy won’t function correctly.

-( id )deepCopy

Calls -copy and returns the result.

-( id )free

Releases the memory occupied by the receiver. Also zeroes the isa pointer of the object. If the object is sent a message at this stage, an immediate runtime error will occur. (Once the memory has been reused, anything can happen.) Override to release other resources held by the receiver.

Identifying objects and classes

Use the following methods to find out about an object’s identity, and to compare it with other objects:

-(Class)class
  • If the receiver is a regular object, returns the class object for the receiver’s class.

  • If the receiver is a class object, returns the receiver.

-(Class)superClass
  • If the receiver is a regular object, returns the class object for the parent class of the receiver’s class, or nil if the receiver’s class is a root class.

  • If the receiver is a class object, returns the class object for the receiver’s parent class, or nil if the receiver represents a root class.

-(MetaClass)metaClass
  • If the receiver is a regular object, returns the metaclass object for the metaclass of the receiver’s class.

  • If the receiver is a class object, returns the metaclass object for the metaclass of the receiver.

-( const char *)name

Returns the name of the receiver’s class.

-( id )self

Returns the receiver. You can get a class object from the class’s name with this method:

Classclassobj = [MyClass self];
-( unsigned int )hash

Returns an integer that can be used to store the object in a hash table. If two objects are equal (as reported by -isEqual:) they will have the same hash value. However, two unequal objects may also share the same hash value.

-( BOOL )isEqual:( id ) obj

Returns YES if the receiver and obj are equal as pointers, otherwise returns NO. Override to implement another relation, such as equality of contents.

-( int )compare:( id ) obj

Returns one of the following values:

  • 0, if [ self isEqual:obj ] returns YES.

  • -1, if the receiver’s value (as a pointer) is less than that of obj.

  • 1, if the receiver’s value (as a pointer) is greater than that of obj.

Override this method if you want to compare your objects in a different way.

Testing object type

Objective-C minimizes the differences between regular and class objects, but sometimes it is helpful to know which is which. In addition, the GNU runtime distinguishes between class and metaclass objects. The following methods let you find out from an object what kind it is:

-( BOOL )isInstance

Returns YES if the receiver is a regular object, otherwise NO.

-( BOOL )isClass

Returns YES if the receiver is a class object, otherwise NO.

-( BOOL )isMetaClass

Returns YES if the receiver is a metaclass object, otherwise NO.

Testing inheritance and conformance

Use the following methods to find out an object’s place in the inheritance hierarchy:

-( BOOL )isKindOf:(Class) classObj
  • If the receiver is an ordinary object, returns YES if the receiver’s class is classObj or a descendant of it, NO otherwise.

  • If the receiver is a class object, returns YES if classObj is the immediate metaclass of the receiver, NO otherwise.

  • If the receiver is a metaclass, returns NO.

-( BOOL )isKindOfClassNamed: ( const char *) className

Same as -isKindOf:, but takes as a parameter the name of a class instead of a class object.

-( BOOL )isMemberOf:(Class) classObj
  • If the receiver is an ordinary object, returns YES if the receiver’s class is classObj, otherwise NO.

  • If the receiver is a class or metaclass object, returns NO.

-( BOOL )isMemberOfClassNamed:( const char *) className

Same as -isMemberOf:, but takes as a parameter the name of a class instead of a class object.

-( BOOL )conformsTo:(Protocol*) prot

Returns YES if the class of the receiver adopts the protocol directly, or if that class directly or indirectly inherits from another class that does.

Information about methods

Use the instance methods listed here to ask regular objects about instance methods, and class objects about class methods.

+( BOOL )instancesRespondTo:( SEL ) sel;

Returns YES if instances of the receiving class respond to the selector sel, otherwise NO. Does not take forwarding into account.

-( BOOL )respondsTo:( SEL ) sel

Returns YES if the receiver responds to the selector sel, otherwise NO. Does not take forwarding into account.

+(struct objc_method_description*) descriptionForInstanceMethod:(SEL)sel

If instances of the receiving class handle the method specified by sel, this method returns a pointer to a description of the method; otherwise it returns a NULL pointer.

The return type is defined as follows in objc-api.h:

struct objc_method_description {
  SEL name;
  char* types;
};

The first member of the structure will be of little use since you already have the selector. The second points to a zero-terminated character string. The string takes the form of type specifiers (as returned by the @encode directive) for the return and parameter types, interleaved with numbers describing offsets of the parameters in the stack frame.

-(struct objc_method_description*) descriptionForMethod:(SEL)sel

If the receiver handles the method specified by sel, this method returns a pointer to a description of the method; otherwise it returns a NULL pointer.

+( IMP )instanceMethodFor:( SEL ) sel

If instances of the receiving class handle the method specified by sel, this method returns a pointer to the implementation of the specified method; otherwise a NULL pointer. You can use this to get a pointer to a method you want to call directly. See Section 1.15 for an example.

-( IMP )methodFor:( SEL ) sel

If the receiver handles the method specified by sel, this method returns a pointer to the method’s code; otherwise a NULL pointer.

Sending messages

Use the following methods to send messages when you won’t know until runtime which message to send:

-(id)perform:(SEL)sel

Sends to the receiver the message specified by the selector sel. Since selectors can be assigned to variables, one part of your code can tell another which message to send.

-(id)perform:(SEL)sel with:(id)obj1

The same as -perform: but also provides the argument obj1 to the method being called.

-(id)perform:(SEL)sel with:(id)obj1 with:(id)obj2

The same as -perform: but also provides two arguments to the method being called.

-(retval_t)performv:(SEL)sel :(arglist_t)args

Like the -perform: methods, but takes a variable-length parameter list. Call this method inside your class’s -forward:: method to delegate the message to another object.

The return type is a typedef for void *. The second parameter describes the parameter types and values. You can treat this as an opaque type; its declaration is in encoding.h.

-(retval_t)forward:(SEL)sel :(arglist_t)args

Invokes -doesNotRecognize. Override as described in Section 1.11 to implement message forwarding. The parameter types are the same as for -performv::.

Posing

The following methods let you change the inheritance hierarchy at runtime:

+(id)poseAs:classObj

Substitutes the receiver for the class represented by classObj. The receiver must be a subclass of the class represented by classObj. The receiver can’t declare any new fields. Call this method before creating any instances of the class represented by classObj or sending it any messages.

This is a way, similar to using categories, to add or override methods to an existing class. In contrast with a category, the posing class can send a message to super , which will execute the method in the class represented by classObj.

-(Class)transmuteClassTo:(Class) classObj

Sets the isa pointer of the receiver to classObj, and returns the previous value of the pointer. This effectively converts the receiver to an instance of the class represented by classObj. This will only work if the receiver’s class is a descendant of the class represented by classObj, and instances of the two classes have the same size. If the call fails, it returns nil.

Enforcing intentions

Each method in the following list generates a runtime error. In each case, when you call the method, pass in the _cmd variable, which the runtime sets up to be the selector of the method you are in.

-(id)subclassResponsibility:(SEL)sel

Call this in a method that you require subclasses to override and implement.

-(id)notImplemented:(SEL)sel

Call this in a method that you have deliberately left unfinished.

-(id)shouldNotImplement:(SEL)sel

Call this in a method that you inherit (and override) but that makes no sense for your subclass to support.

Error handling

The following functions are used for error handling. See Section 1.8 for more information about their usage.

-(id)doesNotRecognize:(SEL)sel

Generates a runtime error by invoking the -error : method on self. The runtime sends this message to an object when the object has failed to respond to, or forward, a message.

-(id)error:(const char*)format,...

Writes an error message to the system log (via the syslog( ) call) and exits the program. The runtime calls this method on self for a variety of error conditions. Override as described in Section 1.8 to customize error handling for a class.

Archiving

The GNU runtime provides the type TypedStream for reading and writing objects to and from archives. Section 1.13 describes this type and its use in saving and restoring objects. The following methods support archiving:

-(id)awake

Does nothing and returns self. Called by the runtime when an object has been reconstructed. Override to customize behavior when your objects are restored.

-(id)write:(TypedStream*)stream

Writes the receiver to the specified stream.

-(id)read:(TypedStream*)stream

Sets the receiver’s fields by reading from the specified stream.

+(id)setVersion:(int)version

Sets the class version number.

+(int)version

Returns the class’s version number, or zero if it has never been set.

+(int)streamVersion:(TypedStream*)stream

Returns the version number of the typed stream.

The NSObject Class

NSObject supports most of the features of Object and adds others. Often the NSObject version of a method will have a more specifically typed return value. For example, -class is declared to return a Class and not just an id.

In defining NSObject, Cocoa first declares the NSObject protocol. (It can be confusing that the class and protocol have the same name; they live in different namespaces.) This allows for other root classes. As long as they implement the NSObject protocol, they can be used in contexts that depend on the methods that NSObject implements.

The NSObject class implements the NSObject protocol along with other useful methods that its descendants may want but that are not part of the protocol and are not important for interchangeability.

Note

Cocoa also declares categories for NSObject, such as NSComparisonMethods, NSURLClient, and others, comprising dozens of additional methods. This handbook discusses a few of these categories (NSCoding, NSKeyValueCoding) separately, but omits them from this section.

In the following sections, the methods are grouped by topic, and marked as being part of the NSObject protocol or class.

Creating, copying, and freeing objects

Section 1.7 discusses how to use the following methods, which create objects, copy objects, and free the memory used by objects:

+(id)alloc

Allocates, clears, and returns a pointer to memory for a new instance of the receiver. Memory comes from the default zone. Returns nil on failure. (NSObject class)

+(id)allocWithZone:(NSZone*)zone

Same as alloc, but uses a specific region of memory. NSZone is not a class but a C type that you should treat as opaque. You can get the zone of an object with the -zone method. You may improve cache performance by creating related objects in the same zone. Passing in a nil parameter means memory will be allocated from the default zone. (NSObject class)

+(void)initialize

Sent by the runtime before the class or any of its descendants is sent a message by the program. Each class gets the message exactly once, and superclasses get the message before subclasses. The NSObject implementation does nothing. Override (first passing the call to super) to perform per-class setup. (NSObject class)

-(id)init

Returns self. This is the designated initializer for NSObject. The Section 1.7 discusses overriding this method. (NSObject class)

+(id)new

Calls +alloc, then -init on the resulting instance, and returns the result. (NSObject class)

+(id)copyWithZone:(NSZone*)zone

Returns the receiver since class objects are unique. Ignores the parameter. Don’t override. (NSObject class)

+(id)mutableCopyWithZone:(NSZone*)zone

Returns the receiver since class objects are unique. Ignores the parameter. Don’t override. (NSObject class)

-(id)copy

Calls -copyWithZone : with a nil zone parameter. NSObject doesn’t implement that method (only the class method of the same name) but many Cocoa classes do. Your class will have to implement -copyWithZone: in order to use -copy. The Section 1.7 discusses how to do this.

-(id)mutableCopy

Calls -mutableCopyWithZone: with a nil zone parameter. NSObject doesn’t implement that method (only the class method of the same name) but many Cocoa classes do. Your class will have to implement -mutableCopyWithZone in order to use -mutableCopy. The Section 1.7 discusses how to do this. (NSObject class)

-(void)dealloc

Deallocates the memory used to store the receiver. Override to release any additional resources managed by your object. Don’t call -dealloc directly if you are using retain/release memory management. (See Section 1.12.) (NSObject class)

+(void)load

Called by the runtime when a class or category is set up for use by the runtime. Deprecated in favor of the +initialize method. (NSObject class)

Identifying objects and classes

Use the following methods to find out about an object’s identity, and to compare it with other objects:

-(Class)class

Returns the class object for the receiver’s class. (NSObject protocol)

-(Class)superclass

Returns the class object of the receiver’s parent class. (NSObject protocol)

-(NSString*)description

Returns a string describing the state of the receiver. The NSObject implementation prints the class name and the runtime address of the instance. Override to provide a string the runtime will use when you print an object using the %@ formatting descriptor with NSLog( ). (NSObject protocol)

-(id)self

Returns the receiver. You can get a class object from the class’s name with this method:

ClasscircleClass = [Circle self];

(NSObject protocol)

-(unsigned)hash

Returns an integer that can be used to store the object in a hash table. If two objects are equal (as reported by the -isEqual: method) they will have the same hash value. However, two unequal objects may also share the same hash value. (NSObject protocol)

-(BOOL)isEqual:(id)object

Returns YES if the receiver and object are equal as pointers, otherwise returns NO. Override to provide different semantics, such as equality of contents. (NSObject protocol)

+(Class)class

Returns the class object that represents the receiver, not (as you might expect) the metaclass object of the metaclass of the receiver. This means that [MyClass class] and [MyClass self] return the same value; the second expression is probably more clear. (NSObject class)

+(NSString*)description

Returns the name of the class. (NSObject class)

+(void)setVersion:(int) version

Sets the class version number. (NSObject class)

+(int)version

Returns the class’s version number, or zero if it has never been set. (NSObject class)

+(Class)superclass

Returns the class object representing the receiver’s parent class. (NSObject class)

Testing inheritance and conformance

Use the following methods to find out about an object’s place in the inheritance hierarchy:

+(BOOL)conformsToProtocol:(Protocol*)prot

Returns YES if the receiver adopts prot directly or inherits directly or indirectly from another class that does. (NSObject class)

-(BOOL)isKindOfClass:(Class)C
  • If the receiver is an ordinary object, returns YES if the receiver’s class is represented by C or is a descendant of the class represented by C, NO otherwise.

  • If the receiver is a class object, returns YES if C represents NSObject, NO otherwise. (This is consistent with the special property that class objects appear to be instances of the root object class.)

  • If the receiver is a metaclass object, returns YES if C represents NSObject or NSObject’s metaclass, NO otherwise.

(NSObject protocol)

-(BOOL)isMemberOfClass:(Class) C

Is part of the NSObject protocol, and does one of the following:

  • If the receiver is an ordinary object, returns YES if C represents the receiver’s class, otherwise NO.

  • If the receiver is a class object, returns YES if C represents the receiver’s metaclass, otherwise NO.

  • If the receiver is a metaclass object, returns YES if C represents NSObject’s metaclass, otherwise NO.

(NSObject protocol)

-(BOOL)conformsToProtocol:(Protocol*)prot

Returns YES if the class of the receiver adopts the protocol directly, or directly or indirectly inherits from another class that does. (NSObject protocol)

-(BOOL)isProxy

Returns NO. (The NSProxy class also implements this method, and returns YES.) (NSObject protocol)

Information about methods

Use the instance methods listed here to ask regular objects about instance methods, and class objects about class methods.

+(BOOL)instancesRespondToSelector:(SEL)sel

Returns YES if instances of the receiving class respond to the selector sel, otherwise NO. Does not take forwarding into account. (NSObject class)

+(IMP)instanceMethodForSelector:(SEL)sel

If instances of the receiving class handle the method specified by sel, returns a pointer to the implementation of the specified method. You can use this to get a pointer to a method you want to call directly. Section 1.15 gives an example.

The Cocoa documentation says that if instances of the receiving class do not handle the specified method, a runtime error occurs. Instead, an apparently valid pointer is returned. You should use code like the following to test for errors:

IMP imp = NULL;
if ([ClassName instancesRespondToSelector:sel])
  imp = [ClassName
         instanceMethodForSelector:sel];

After executing these instructions, imp will still be NULL if the class’s instances do not handle the method specified by sel. (NSObject class)

+(NSMethodSignature*) instanceMethodSignatureForSelector:(SEL)sel

If instances of the receiving class handle the method specified by sel, returns a description of the method’s signature for the specified method; otherwise returns nil. (NSObject class)

-(IMP)methodForSelector:(SEL)sel

If the receiver handles the method specified by sel, this method returns a pointer to the method’s code. You can use this to get a pointer to a method you want to call directly. Section 1.15 gives an example.

The Cocoa documentation says that if the receiver does not handle the specified method, a runtime error occurs. Instead, an apparently-valid pointer is returned. You should use code like the following to test for errors:

IMP 
                           imp = NULL;
if ([obj respondsToSelector:sel])
  imp = [obj methodForSelector:sel];

After executing these instructions, imp will still be NULL if the receiver does not handle the method specified by sel. (NSObject class)

-(NSMethodSignature*)methodSignatureForSelector:(SEL)sel

If the receiver handles the method specified by sel, this method returns a description of the method; otherwise it returns nil. (NSObject class)

-(BOOL)respondsToSelector:(SEL)sel

Returns YES if the receiver responds to the selector sel; otherwise NO. Does not take forwarding into account. (NSObject protocol)

Sending messages

Use the following methods to send messages when you won’t know until runtime which message to send:

-(id)performSelector:(SEL)sel

Sends to the receiver the message specified by the selector sel. Since selectors can be assigned to variables, one part of your code can tell another which message to send.

-(id)performSelector:(SEL)sel withObject:(id)obj1

The same as -performSelector:, but also provides the argument obj1 to the method being called.

-(id)performSelector:(SEL)sel withObject:(id) obj1 withObject:(id)obj2

The same as -performSelector:, but also provides two arguments to the method being called. If you need to pass more than two parameters, construct an NSInvocation instance. Section 1.11 gives an example. (NSObject protocol)

-(void)forwardInvocation:(NSInvocation*)inv

Invokes -doesNotRecognizeSelector:. Section 1.11 describes how to override this to implement message forwarding. (NSObject class)

Posing

This method lets you modify the inheritance hierarchy at runtime:

+(void)poseAsClass:(Class)classObj

Substitutes the receiver for the class represented by classObj. The receiver must be a subclass of the class represented by classObj. The receiver can’t declare any new fields. You should call this method before creating any instances of the class represented by classObj or sending it any messages.

This is a way, similar to using categories, to add or override methods to an existing class. In contrast with a category, the posing class can send a message to super and execute the method in the class represented by classObj. (NSObject class)

Error handling

The following functions are used for error handling. See Section 1.8 for more information about their usage.

-(void)doesNotRecognizeSelector:(SEL)sel

Raises an NSInvalidArgument exception. The runtime sends this message to an object when the object has failed to respond to or forward a message.

You can “un-implement” a method as follows:

-(void) methodName {
  [self doesNotRecognizeSelector: _cmd];
}

The class implementing this code will now behave as if it had no methodName.

You could also make an object handle any message without failing by overriding -doesNotRecognizeSelector:, but you should override -forwardInvocation: instead. (NSObject class)

Archiving

These are peripheral methods that support saving objects to disk and restoring them. Section 1.13 provides more information on this topic.

-(id)awakeAfterUsingCoder:(NSCoder*)coder

Returns the receiver. Called by NSCoder when it has decoded the receiver. Override this to return some other object. You are responsible for releasing the receiver if you return a different object. (NSObject class)

-(Class)classForCoder

Returns the receiver’s class. Override to substitute another class during archiving. Called by NSCoder. (NSObject class)

-(id)replacementObjectForCoder:(NSCoder*)coder

Returns self. Override to substitute another object for the receiver during archiving. Called by NSCoder. (NSObject class)

Reference counting

These methods support reference counting or return information about an object’s allocation. See Section 1.12 for more information.

-(id)retain

Increments the receiver’s reference count and returns the receiver. (NSObject protocol)

-(unsigned)retainCount

Returns the receiver’s reference count. (NSObject protocol)

-(oneway void)release

Decrements the receiver’s reference count, and sends it the -dealloc message if the count reaches zero. The oneway keyword specifies that the caller can send the message asynchronously. (See Section 1.6.) (NSObject protocol)

-(id)autorelease

Adds the receiver to the current autorelease pool. Returns the receiver. (NSObject protocol)

-(NSZone*)zone

Returns the memory zone in which the receiver was allocated. NSZone is not a class but a C type that you should treat as opaque. You can use the value returned by this method as a parameter to -copyWithZone : or -allocWithZone:. Cocoa creates a default zone when a program starts up, and normally you will allocate objects from this zone. You may be able to improve cache behavior by creating related objects in the same zone. See the Cocoa documentation for NSCreateZone( ) and related functions. (NSObject protocol)

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.212.124