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>
.