This question already has answers here:
Closed 6 years ago.
Is there a difference between relating to an Object
in a 'Polymorphic' way with the type id
than as NSObject *
?
In what way is:
NSString* aString = @"Hello";
id anObj = aString;
different than:
NSString* aString = @"Hello";
NSObject* anObj = aString;
id
is a special keyword used in Objective-C to mean “some kind of object.” It does not contain isa
pointer(isa
, gives the object access to its class and, through the class, to all the classes it inherits from), So you lose compile-time information about the object.
NSString* aString = @"Hello";
id anObj = aString;
NSObject
contain isa
pointer.
NSString* aString = @"Hello";
NSObject* anObj = aString;
From Objective-C Is a Dynamic Language
Consider the following code:
id someObject = @"Hello, World!";
[someObject removeAllObjects];
In this case, someObject will point to an NSString
instance, but the compiler knows nothing about that instance beyond the fact that it’s some kind of object. The removeAllObjects
message is defined by some Cocoa or Cocoa Touch objects (such as NSMutableArray
) so the compiler doesn’t complain, even though this code would generate an exception at runtime because an NSString object can’t respond to removeAllObjects
.
Rewriting the code to use a static type:
NSString *someObject = @"Hello, World!";
[someObject removeAllObjects];
means that the compiler will now generate an error because removeAllObjects
is not declared in any public NSString
interface that it knows about.
id
is generic. By using id
you're telling the compiler that you will fill in details about usage later. The compiler assumes that any code you have is correct and doesn't warn you about anything. At runtime checks are made to verify what you're trying to do and you will get an exception if your code is wrong.
NSObject
is specific. By using NSObject
you're telling the compiler exactly what the object is. When you try to call methods on it they will be checked against what NSObject
understands. You will get compile time errors if you make a mistake.
All that said, you can just cast in both cases to get to another Class type.
Your concern is what you're going to do with the reference in the future. Generally, using NSObject
doesn't have any benefits.
When using id, you can send it any known message and when using NSObject *, you can only send it messages declared by NSObject (not methods of any subclass) or else it will generate a warning.