Question

If I do the following, the compiler does not complain:

id foo;
[foo retain];

However, if I do the following, the compiler does complain:

id<NSCopying> bar;
[bar retain];

Specifically, it says:

Instance method '-retain' not found (return type defaults to 'id')

Why is this? I thought an id pointed to a generic Objective-C object, and that I could pass retain to any Objective-C object.

Note this is a warning, not an error, so I can still compile the code and it seems to work. I also notice I can do the following to suppress the warning:

[(id)bar retain];

But I would think id<NSCopying> is a subtype of id, so anything that can be done on an id can be done on an id <NSCopying>...

Was it helpful?

Solution

You can't necessarily send retain to any Objective-C object. retain is part of the NSObject protocol. It so happens that all of Cocoa conforms to NSObject, but it is still not really universal from the standpoint of the language (it is possible to define a class that does not conform to NSObject or inherit from the NSObject class; it just isn't very useful).

Declaring something as id<NSCopying> means "Only let me send messages in the NSCopying protocol" — and NSCopying does not include retain. In order to send messages from the NSObject protocol, you must declare the variable as either id (in which case no type-checking occurs), id<NSObject> (in which case you can only send messages in the NSObject protocol) or as an instance of a class that conforms to NSObject.

In the case where you are declaring something as id<NSCopying>, you usually want to send the object copy instead of retain, since that's the whole point of declaring it that way. If NSCopying is standing in here for a protocol of your own, you can make the protocol itself conform to NSObject by defining it like this:

@protocol YourProtocol <NSObject>

And if you really need to declare a variable that conforms to two protocols (this is pretty unusual, but can crop up now and then), you can just declare it with a comma-separated list of protocols, like id<NSCopying,NSObject>.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top