- Inherits from:
- none (NSObject is a root class)
- Conforms to:
- NSObject
Declared in:
- Foundation/NSObject.h
- Foundation/NSArchiver.h
- Foundation/NSConnection.h
- Foundation/NSPortCoder.h
- Foundation/NSURL.h
NSObject is the root class of most Objective-C class hierarchies. Through NSObject, objects inherit a basic interface to the run-time system and the ability to behave as Objective-C objects.
+ alloc | |
+ allocWithZone: | |
- init (designated initializer) |
NSObject is the root class of most Objective-C class hierarchies; it has no superclass. From NSObject, other classes inherit a basic interface to the run-time system for the Objective-C language, and its instances obtain their ability to behave as objects.
NSObject adopts the NSObject protocol. The NSObject protocol allows for multiple root objects. For example, NSProxy is another root class-it does not inherit from NSObject but adopts the NSObject protocol so that it shares a common interface with other Objective-C objects. Some of the methods discussed below are declared by NSObject protocol, not this class.
Among other things, the NSObject class provides inheriting classes with a framework for creating, initializing, deallocating, copying, comparing, archiving and distributing objects, for performing methods selected at run-time, for querying an object about its methods and its position in the inheritance hierarchy, and for forwarding messages to other objects. For example, to ask an object what class it belongs to, you'd send it a class message. To find out whether it implements a particular method, you'd send it a respondsToSelector: message.
The NSObject class is mostly an abstract class; programs use instances of classes that inherit from NSObject, but rarely instances of NSObject itself.
Every object that inherits directly or indirectly from NSObject is connected to the run-time system through its isa instance variable. isa identifies the object's class; it references a structure that's compiled from the class definition. Through isa, an object can find whatever information it needs at run-time-such as its place in the inheritance hierarchy, the size and structure of its instance variables, and the location of the method implementations it can perform in response to messages.
The installation of the class structure-the initialization of isa-is one of the responsibilities of class methods that create (allocate memory for) new instances: alloc, allocWithZone: and new. In other words, a small part of instance initialization is taken care of by these creation methods; it's not left to the methods, such as init, that initialize individual objects with their particular characteristics.
The run-time system treats methods defined in the root class in a special way:
Instance methods defined in a root class can be performed both by instances and by class objects.
Therefore, all class objects have access to the instance methods defined in the root class. Any class object can perform any root instance method, provided it doesn't have a class method with the same name.
For example, a class object could be sent messages to perform NSObject's respondsToSelector: and performSelector:withObject: instance methods:
SEL method = @selector(riskAll:); if ([MyClass respondsToSelector:method]) [MyClass performSelector:method withObject:self];
Note that the only instance methods available to a class object are those defined in its root class. In the example above, if MyClass had reimplemented either respondsToSelector: or performSelector:withObject:, those new versions would be available only to instances. The class object for MyClass could perform only the versions defined in the NSObject class. (Of course, if MyClass had implemented respondsToSelector: or performSelector:withObject: as class methods rather than instance methods, the class would perform those new versions.)
The NSObject class defines a number of methods that subclasses are expected to override. Often, NSObject's default implementation simply returns self. Putting these "empty" methods in the NSObject class serves two purposes:
NSObject
- - autorelease
- - class
- - conformsToProtocol:
- - description
- - hash
- - isEqual:
- - isKindOfClass:
- - isMemberOfClass:
- - isProxy
- - performSelector:
- - performSelector:withObject:
- - performSelector:withObject:withObject:
- - release
- - respondsToSelector:
- - retain
- - retainCount
- - self
- - superclass
- - zone
- Initializing the class
- + initialize
- + load
- Creating, copying, and deallocating objects
- + new
- + alloc
- + allocWithZone:
- - init
- - copy
- + copyWithZone:
- - mutableCopy
- + mutableCopyWithZone:
- - dealloc
- Identifying classes
- + class
- + superclass
- Testing class functionality
- + instancesRespondToSelector:
- Testing protocol conformance
- + conformsToProtocol:
- Obtaining method information
- - methodForSelector:
- + instanceMethodForSelector:
- + instanceMethodSignatureForSelector:
- - methodSignatureForSelector:
- Describing objects
- + description
- Posing
- + poseAsClass:
- Sending messages
- - performSelector:withObject:afterDelay:
- - performSelector:withObject:afterDelay:inModes:
- + cancelPreviousPerformRequestsWithTarget:selector:object:
- Forwarding messages
- - forwardInvocation:
- Error handling
- - doesNotRecognizeSelector:
- Archiving
- - awakeAfterUsingCoder:
- - classForArchiver
- - classForCoder
- - classForPortCoder
- - replacementObjectForArchiver:
- - replacementObjectForCoder:
- - replacementObjectForPortCoder:
- + setVersion:
- + version
- Working with NSDistantObjectRequests
- - connection:handleRequest:
- Working with URL clients
- - URLResourceDidFinishLoading:
- - URLResourceDidCancelLoading:
- - URL:resourceDataDidBecomeAvailable:
- - URL:resourceDidFailLoadingWithReason:
+ (id)alloc
An init... method should be used to complete the initialization process. For example:
TheClass *newObject = [[TheClass alloc] init];
Subclasses shouldn't override alloc to include initialization code. Instead, class-specific versions of init... methods should be implemented for that purpose. Class methods can also be implemented to combine allocation and initialization, similar to the new class method.
Note that it's your responsibility to release objects (with either release or autorelease) returned by alloc... methods.
See Also: - init
+ (id)allocWithZone:(NSZone
*)zone
NSDefaultMallocZone()
).An init... method should be used to complete the initialization process. For example:
TheClass *newObject = [[TheClass allocWithZone:someZone] init];
Subclasses shouldn't override allocWithZone: to include any initialization code. Instead, class-specific versions of init... methods should be implemented for that purpose.
When one object creates another, it's often a good idea to make sure they're both allocated from the same region of memory. The zone method (declared in the NSObject protocol) can be used for this purpose; it returns the zone where the receiver is located. For example:
id myCompanion = [[TheClass allocWithZone:[self zone]] init];
Note that it's your responsibility to release objects (with either release or autorelease) returned by alloc... methods.
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget
selector:(SEL)aSelector
object:(id)anArgument
+ (Class)class
Only refer to a class by name when it is the receiver of a message. In all other cases, the class object must be obtained through this, or a similar method. For example, here SomeClass is passed as an argument to the isKindOfClass: method (declared in the NSObject protocol):
BOOL test = [self isKindOfClass:[SomeClass class]];
See Also: - class (NSObject protocol)
+ (BOOL)conformsToProtocol:(Protocol
*)aProtocol
A
class is said to "conform to" a protocol if it adopts the protocol
or inherits from another class that adopts it. Protocols are adopted
by listing them within angle brackets after the interface declaration. For
example, here MyClass adopts the fictitious AffiliationRequests
and Normalization
protocols:
@interface MyClass : NSObject <AffiliationRequests, Normalization>
A class also conforms to any protocols that are incorporated in the protocols it adopts or inherits. Protocols incorporate other protocols in the same way classes adopt them. For example, here the AffiliationRequests protocol incorporates the Joining protocol:
@protocol AffiliationRequests <Joining>
If a class adopts a protocol that incorporates another protocol, it must also implement all the methods in the incorporated protocol or inherit those methods from a class that adopts it.
This method determines conformance solely on the basis of the formal declarations in header files, as illustrated above. It doesn't check to see whether the methods declared in the protocol are actually implemented-that's the programmer's responsibility.
The Protocol required as this method's argument can be specified using the @protocol() directive:
BOOL canJoin = [MyClass conformsToProtocol:@protocol(Joining)];
See Also: - conformsToProtocol:
+ (id)copyWithZone:(NSZone
*)zone
See Also: - copy
+ (NSString *)description
NSObject's implementation of this method simply prints the name of the class.
See Also: - description (NSObject protocol)
+ (void)initialize
For example, if the first message your program sends is this:
[NSApplication new]
the run-time system invokes these three initialize messages:
[NSObject initialize]; [NSResponder initialize]; [NSApplication initialize];
because NSApplication is a subclass of NSResponder and NSResponder is a subclass of NSObject. All the initialize messages precede the new message.
If your program later begins to use the NSText class,
[NSText instancesRespondToSelector:someSelector]
the run-time system invokes these additional initialize messages:
[NSView initialize]; [NSText initialize];
because NSText inherits from NSObject, NSResponder, and NSView. The instancesRespondToSelector: message is sent only after all these classes are initialized. Note that the initialize messages to NSObject and NSResponder aren't repeated.
You can implement your own versions of initialize to provide class-specific initialization as needed.
Normally the run-time system sends a class just one initialize message. However, if for some reason an application or the run-time system generates additional initialize messages, it is a good idea to prevent code from being invoked more than once:
+ (void)initialize { static BOOL tooLate = NO; if ( !tooLate ) { /* put initialization code here */ tooLate = YES; } }
See Also: - init, - class (NSObject protocol)
+ (IMP)instanceMethodForSelector:(SEL)aSelector
Use this method to ask the class object for the implementation of instance methods only. To ask the class for the implementation of a class method, send the methodForSelector: instance method to the class instead.
instanceMethodForSelector:, and the function pointer it returns, are subject to the same constraints as those described for methodForSelector:. See methodForSelector: for description of the IMP return value.
+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector
See Also: - methodSignatureForSelector:
+ (BOOL)instancesRespondToSelector:(SEL)aSelector
If aSelector messages are forwarded to other objects, instances of the class will be able to receive those messages without error even though this method returns NO.
See Also: - forwardInvocation:
+(void)load
load is usually invoked before initialize. It is usually the very first method sent to the class, although this isn't guaranteed. The order in which classes are loaded is also not guaranteed, to the point that superclasses aren't even guaranteed to be loaded before all of their subclasses. Because you can't rely on other classes being loaded at the point when your class is sent a load message, you should be extremely careful when sending messages to other classes from within your load method.
Due to the amount of uncertainty about the environment at the point that load is invoked, you should avoid using load whenever possible. All class-specific initialization should be done in the class's initialize method.
See Also: + load (NSProxy)
+ (id)mutableCopyWithZone:(NSZone
*)zone
+ (id)new
This method is a combination of alloc and init. Like alloc, it initializes the isa instance variable of the new object so it points to the class data structure. It then invokes the init method to complete the initialization process.
Unlike alloc, new is sometimes reimplemented in subclasses to invoke a class-specific initialization method. If the init... method includes arguments, they're typically reflected in a new... method as well. For example:
+ newArg:(int)tag arg:(struct info *)data { return [[self alloc] initArg:tag arg:data]; }
However, there's little point in implementing a new... method if it's simply a shorthand for alloc and init..., as shown above. Often new... methods will do more than just allocation and initialization. In some classes, they manage a set of instances, returning the one with the requested properties if it already exists, allocating and initializing a new instance only if necessary. For example:
+ newArg:(int)tag arg:(struct info *)data { MyClass *theInstance; if ( theInstance = findTheObjectWithTheTag(tag) ) return theInstance; return [[self alloc] initArg:tag arg:data]; }
Although it's appropriate to define new new... methods in this way, the alloc and allocWithZone: methods should never be augmented to include initialization code.
+ (void)poseAsClass:(Class)aClass
This facility allows you to add methods to an existing class by defining them in a subclass and having the subclass substitute for the existing class. The new method definitions will be inherited by all subclasses of the superclass. Care should be taken to ensure that this doesn't generate errors.
A subclass that poses as its superclass still inherits from the superclass. Therefore, none of the functionality of the superclass is lost in the substitution. Posing doesn't alter the definition of either class.
Posing is useful as a debugging tool, but category definitions are a less complicated and more efficient way of augmenting existing classes. Posing admits only two possibilities that are absent from categories:
super
, incorporate
the superclass method it overrides. A method defined in a category
can replace a method defined elsewhere by the class, but it can't
incorporate the method it replaces.+ (void)setVersion:(int)aVersion
See Also: + version
+ (Class)superclass
See Also: + class, - superclass (NSObject protocol)
+ (int)version
Version numbers are needed for decoding or unarchiving, so older versions of an object can be detected and decoded correctly.
Caution should be taken when obtaining the version from within NSCoding protocol or other methods. Use the class name explicitly when getting a class version number:
version = [MyClass version];
Don't simply send version to the return value of class-a subclass version number may be returned instead.
See Also: + setVersion:, - versionForClassName: (NSCoder)
- (id)awakeAfterUsingCoder:(NSCoder
*)aDecoder
This method is invoked by NSCoder. NSObject's implementation simply returns self.
See Also: - classForCoder, - replacementObjectForCoder:, - initWithCoder: NSCoding protocol)
- (Class)classForArchiver
See Also: - replacementObjectForArchiver:
- (Class)classForCoder
See Also: - awakeAfterUsingCoder:, - replacementObjectForCoder:
- (Class)classForPortCoder
See Also: - replacementObjectForPortCoder:
- (BOOL)connection:(NSConnection
*)connection
handleRequest:(NSDistantObjectRequest
*)doreq
- (id)copy
NSObject does
not itself support the NSCopying protocol. Subclasses must support
the protocol and implement the copyWithZone: method. A subclass
version of the copyWithZone: method should pass the
message to super
unless
the subclass descends directly from NSObject, in which case the
method must not invoke super
's
method.
- (void)dealloc
You never send a dealloc message directly. Instead, an object's dealloc method is invoked indirectly through the release NSObject protocol method. See the introduction to the Foundation Kit for more details on the use of these methods.
Subclasses must implement their own versions of dealloc to allow the deallocation of any additional memory consumed by the object-such as dynamically allocated storage for data, or object instance variables owned by the deallocated object. After performing the class-specific deallocation, the subclass method should incorporate superclass versions of dealloc through a message to super:
- (void)dealloc { [companion release]; NSZoneFree(private, [self zone]) [super dealloc]; }
See Also: - autorelease (NSObject protocol), - release (NSObject protocol)
- (void)doesNotRecognizeSelector:(SEL)aSelector
doesNotRecognizeSelector: messages are generally sent only by the run-time system. However, they can be used in program code to prevent a method from being inherited. For example, an NSObject subclass might renounce the copy or init method by reimplementing it to include a doesNotRecognizeSelector: message as follows:
- copy { [self doesNotRecognizeSelector:_cmd]; }
The _cmd
variable
identifies the current selector; in this example, it identifies
the selector for the copy method. This
code prevents instances of the subclass from responding to copy messages
or superclasses from forwarding copy messages-although respondsToSelector: will still report
that the receiver has access to a copy method.
See Also: - forwardInvocation:
- (void)forwardInvocation:(NSInvocation
*)anInvocation
Note: To respond to methods that your object does not itself recognize, you must override methodSignatureForSelector: in addition to forwardInvocation:. The mechanism for forwarding messages uses information obtained from methodSignatureForSelector: to create the NSInvocation object to be forwarded. Your overriding method must provide an appropriate method signature for the given selector, either by preformulating one or by asking another object for one. |
The forwardInvocation: message thus allows an object to establish relationships with other objects that will, for certain messages, act on its behalf. The forwarding object is, in a sense, able to "inherit" some of the characteristics of the object it forwards the message to.
An implementation of the forwardInvocation: method has two tasks:
In
the simple case, in which an object forwards messages to just one
destination (such as the hypothetical friend
instance
variable in the example below), a forwardInvocation: method
could be as simple as this:
- (void)forwardInvocation:(NSInvocation *)invocation { if ([friend respondsToSelector:[invocation selector]]) [invocation invokeWithTarget:friend]; else [self doesNotRecognizeSelector:aSelector]; }
The message that's
forwarded must have a fixed number of arguments; variable numbers
of arguments (in the style of printf()
)
are not supported.
The return value of the forwarded message is returned to the original sender. All types of return values can be delivered to the sender: ids, structures, double-precision floating point numbers.
Implementations of the forwardInvocation: method can do more than just forward messages. forwardInvocation: can, for example, be used to consolidate code that responds to a variety of different messages, thus avoiding the necessity of having to write a separate method for each selector. A forwardInvocation: method might also involve several other objects in the response to a given message, rather than forward it to just one.
NSObject's implementation of forwardInvocation: simply invokes the doesNotRecognizeSelector: method; it doesn't forward any messages. Thus, if you choose not to implement forwardInvocation:, unrecognized messages will raise an exception.
- (id)init
TheClass *newObject = [[TheClass alloc] init];
An object isn't ready to be used until it has been initialized. The version of the init method defined in the NSObject class does no initialization; it simply returns self.
Subclass
versions of this method should return the new object (self)
after it has been successfully initialized. If it can't be initialized,
they should release the object and return nil
.
In some cases, an init method might release
the new object and return a substitute. Programs should therefore
always use the object returned by init,
and not necessarily the one returned by alloc or allocWithZone:, in subsequent code.
Every
class must guarantee that the init method
either returns a fully functional instance of the class or raises
an exception. Typically this means overriding the method to add
class-specific initialization code. Subclass versions of init need
to incorporate the initialization code for the classes they inherit from,
through a message to super
:
- init { if (self = [super init]) { /* class-specific initialization goes here */ } return self; }
Note that the
message to super
precedes
the initialization code added in the method. This ensures that initialization
proceeds in the order of inheritance.
Subclasses often define init... methods with additional arguments to allow specific values to be set. The more arguments a method has, the more freedom it gives you to determine the character of initialized objects. Classes often have a set of init... methods, each with a different number of arguments. For example:
- init; - initArg:(int)tag; - initArg:(int)tag arg:(struct info *)data;
The convention is that at least one of these methods, usually the one with the most arguments, includes a message to super to incorporate the initialization of classes higher up the hierarchy. This method is called the designated initializer for the class. The other init... methods defined in the class directly or indirectly invoke the designated initializer through messages to self. In this way, all init... methods are chained together. For example:
- init { return [self initArg:-1]; } - initArg:(int)tag { return [self initArg:tag arg:NULL]; } - initArg:(int)tag arg:(struct info *)data { [super init. . .]; /* class-specific initialization goes here */ }
In this example, the initArg:arg: method is the designated initializer for the class.
If a subclass does any initialization of its own, it must define its own designated initializer. This method should begin by sending a message to super to perform the designated initializer of its superclass. Suppose, for example, that the three methods illustrated above are defined in the B class. The C class, a subclass of B, might have this designated initializer:
- initArg:(int)tag arg:(struct info *)data arg:anObject { [super initArg:tag arg:data]; /* class-specific initialization goes here */ }
If inherited init... methods are to successfully initialize instances of the subclass, they must all be made to (directly or indirectly) invoke the new designated initializer. To accomplish this, the subclass is obliged to cover (override) only the designated initializer of the superclass. For example, in addition to its designated initializer, the C class would also implement this method:
- initArg:(int)tag arg:(struct info *)data { return [self initArg:tag arg:data arg:nil]; }
This ensures that all three methods inherited from the B class also work for instances of the C class.
Often the designated initializer of the subclass overrides the designated initializer of the superclass. If so, the subclass need only implement the one init... method.
These
conventions maintain a direct chain of init... links,
and ensure that the new method and all inherited init... methods
return usable, initialized objects. They also prevent the possibility
of an infinite loop wherein a subclass method sends a message (to super
)
to perform a superclass method, which in turn sends a message (to self)
to perform the subclass method.
This init method is the designated initializer for the NSObject class. Subclasses that do their own initialization should override it, as described above.
- (IMP)methodForSelector:(SEL)aSelector
aSelector must be a valid, non-nil selector. If in doubt, use the respondsToSelector: method to check before passing the selector to methodForSelector:.
IMP is defined as a pointer to a function that returns an id and takes a variable number of arguments (in addition to the two "hidden" arguments-self and _cmd-that are passed to every method implementation):
typedef id (*IMP)(id, SEL, ...);
This definition serves as a prototype for the function pointer methodForSelector: returns. It's sufficient for methods that return an object and take object arguments. However, if the aSelector method takes different argument types or returns anything but an id, its function counterpart will be inadequately prototyped. Lacking a prototype, the compiler will promote floats to doubles and chars to ints, which the implementation won't expect. It will therefore behave differently (and erroneously) when performed as a method.
To remedy this situation, it's
necessary to provide your own prototype. In the example below, the declaration
of the test variable serves to prototype
the implementation of the isEqual: method. test is
defined as a pointer to a function that returns a BOOL
and
takes an id argument (in addition to
the two "hidden" arguments). The value returned by methodForSelector: is
then similarly cast to be a pointer to this same function type:
BOOL (*test)(id, SEL, id); test = (BOOL (*)(id, SEL, id))[target methodForSelector:@selector(isEqual:)]; while ( !test(target, @selector(isEqual:), someObject) ) { ... }
In some cases,
it might be clearer to define a type (similar to IMP
)
that can be used both for declaring the variable and for casting
the function pointer methodForSelector: returns.
The example below defines the EqualIMP type
for just this purpose:
typedef BOOL (*EqualIMP)(id, SEL, id); EqualIMP test; test = (EqualIMP)[target methodForSelector:@selector(isEqual:)]; while ( !test(target, @selector(isEqual:), someObject) ) { ... }
Either way, it's important to cast the return value of methodForSelector: to the appropriate function type. It's not sufficient to simply call the function returned by methodForSelector: and cast the result of that call to the desired type. This can result in errors.
The advantage of obtaining a method's implementation and calling it as a function is that you can invoke the implementation multiple times within a loop, or similar C construct, without the overhead of Objective-C messaging.
See Also: + instanceMethodForSelector:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
This method is used in the implementation of protocols. This method is also used in situations where an NSInvocation object must be created, such as during message forwarding. If your object maintains a delegate or is capable of handling messages that it does not directly implement, you should override this method to return an appropriate method signature.
See Also: + instanceMethodSignatureForSelector:, - forwardInvocation:
- (id)mutableCopy
- (void)performSelector:(SEL)aSelector
withObject:(id)anArgument
afterDelay:(NSTimeInterval)delay
See Also: + cancelPreviousPerformRequestsWithTarget:selector:object:
- (void)performSelector:(SEL)aSelector
withObject:(id)anArgument
afterDelay:(NSTimeInterval)delay
inModes:(NSArray *)modes
The inModes parameter contains an array of strings that identify the modes to associate with the timer performing the selector. This timer becomes associated with each of the given modes until its invalidate method is invoked.
See Also: - performSelector:withObject:afterDelay:, addTimer:forMode: (NSRunLoop), invalidate (NSTimer)
- (id)replacementObjectForArchiver:(NSArchiver
*)anArchiver
See Also: - classForArchiver
- (id)replacementObjectForCoder:(NSCoder
*)aCoder
See Also: - classForCoder, - awakeAfterUsingCoder:
- (id)replacementObjectForPortCoder:(NSPortCoder
*)aCoder
Subclasses that want to be passed by copy instead of by reference must override this method and return self. The following example shows how to support object replacement both by copy and by reference:
- (id)replacementObjectForPortCoder:(NSPortCoder *)encoder { if ([encoder isByref]) return [NSDistantObject proxyWithLocal:self connection:[encoder connection]]; else return self; }
See Also: - classForPortCoder
- (void)URLResourceDidCancelLoading:(NSURL
*)sender
- (void)URLResourceDidFinishLoading:(NSURL
*)sender
- (void)URL:(NSURL
*)sender
resourceDataDidBecomeAvailable:(NSData
*)newBytes
- (void)URL:(NSURL
*)sender
resourceDidFailLoadingWithReason:(NSString
*)reason