Richard Venable
Richard Venable

Reputation: 8695

Objective C casting (id) vs. casting as an explicit class

Often in objective C, you know an object is a kind of particular class, so you cast it into that class to continue using it:

NSObject *object;
NSString *string = (NSString *)object;

But, this has bothered me for some time - is there any advantage to writing out "NSString *" in that cast as opposed to the shorter (id):

NSObject *object;
NSString *string = (id)object;

I typically favor verbose Objective-C because the language is designed for readability, but I can't figure out any advantage of being verbose in this case.

Upvotes: 3

Views: 3313

Answers (2)

Vlad Papko
Vlad Papko

Reputation: 13302

I think that the best way is not using down-casting at all by developing more thought-out architecture.
Constructions like this NSString *string = (NSString *)object; simply hide compiler warning and don't make any run-time casting.
But there are some situations when compiler can't know what kind of object is returned by method. For example: [NSDictionary valueForKey:] returns object of id type that is reference to object of any class. It is so because NSDictionary could contain any objects of any class and Objective C doesn't support templates where you could provide class of objects that collection will contain due initialisation.
In such situations usually used constructions like this:

id object = dictionary[key];
NSString *string = object;

Update:
However if consider situation when method returns object of kind NSObject that is really NSString then for compiler it doesn't matter what kind of casting you use: (id) or (NSString *) . But logically it's better to use (NSString *) as it shows kind of object that you expect. I mean that it is more clear for person who will read your code.

Upvotes: 0

bbum
bbum

Reputation: 162712

Anything you can do to give the compiler more precise and accurate information about the types in play, the more the compiler can validate your code. The id type basically means *this thing responds to any method I've ever seen declared` to the compiler wherein a specific cast narrows it to only the methods that class supports.

In general, casts are to be avoided. They generally indicate poor architecture. Not always, though, as they are oft unavoidable when dynamically generating UI or parsing JSON.

In that case, a construct that boils down to this is oft helpful:

NSObject *object;
NSAssert((!object) || [object isKindOfClass:[NSString class]]);
NSString *string = (NSString *)object;

That forces verification of the I know better than the compiler to runtime. (And, yes, it explicitly allows nil to pass through in this case.... your specific needs may vary.)

Upvotes: 7

Related Questions