【问题标题】:Why does retain on an id<NSCopying> give a warning?为什么在 id<NSCopying> 上保留会发出警告?
【发布时间】:2013-09-18 14:30:24
【问题描述】:

如果我执行以下操作,编译器不会抱怨:

id foo;
[foo retain];

但是,如果我执行以下操作,编译器会抱怨:

id<NSCopying> bar;
[bar retain];

具体来说:

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

这是为什么?我认为id 指向一个通用的Objective-C 对象,我可以将retain 传递给任何Objective-C 对象。

请注意,这是一个警告,而不是错误,所以我仍然可以编译代码并且它似乎可以工作。我还注意到我可以执行以下操作来抑制警告:

[(id)bar retain];

但我认为id&lt;NSCopying&gt;id 的子类型,所以可以在id 上完成的任何事情都可以在id &lt;NSCopying&gt; 上完成...

【问题讨论】:

  • 这里有一个小的上下文/概念差异,id &lt;NSCopying&gt; 真正的意思是“任何实现NSCopying 但没有别的类的对象”,或者它是一个编译器错误。
  • 使用id&lt;NSObject,NSCopying&gt; bar 消除问题。
  • 能像NSCopying* bar;这样说吗?
  • @rmaddy 但这并不能回答“为什么”。
  • @H2CO3 不,你已经这样做了。我认为没有必要重复你所说的话。 :)

标签: ios objective-c release retain


【解决方案1】:

您不一定要将retain 发送到任何 Objective-C 对象。 retain 是 NSObject 协议的一部分。碰巧所有的 Cocoa 都符合 NSObject,但从语言的角度来看,它仍然不是真正的通用(可以定义一个不符合 NSObject 的类或从 NSObject 类继承;它只是不是非常有用)。

声明为id&lt;NSCopying&gt; 的意思是“只允许我在NSCopying 协议中发送消息”——而NSCopying 不包括retain。为了从 NSObject 协议发送消息,您必须将变量声明为 id(在这种情况下不进行类型检查)、id&lt;NSObject&gt;(在这种情况下您只能在 NSObject 协议中发送消息)或声明为符合 NSObject 的类的实例。

如果您将某个东西声明为id&lt;NSCopying&gt;,您通常希望发送对象copy 而不是retain,因为这就是以这种方式声明它的全部意义所在。如果 NSCopying 在这里代表您自己的协议,您可以通过如下定义使协议本身符合 NSObject:

@protocol YourProtocol <NSObject>

如果你真的需要声明一个符合两个协议的变量(这很不寻常,但有时会出现),你可以用逗号分隔的协议列表来声明它,比如id&lt;NSCopying,NSObject&gt; .

【讨论】:

  • 哦,有趣。我使用id&lt;NSCopying&gt; 的原因是因为我看到NSMutableDictionary 采用该类型作为setObject:forKey: 的键。这就是它使用它而不是id 的原因 - 所以它发送密钥copy 而不是retain?另一个问题是,似乎copy 无论如何都是NSObject 的方法,而不是NSCopying...看来我想要的是id&lt;NSCopying,NSObject&gt;,我现在将使用它。
  • NSObject&lt;NSCopying&gt;* 通常更可取,因为 NSObject 类的许多方法不是协议 NSObject 的一部分。
  • @Claudiu:我认为你对 NSObject 有两个东西——一个类和一个协议——这一事实感到有些困惑。 NSObject 类符合 NSObject 协议。 copy 方法由 NSObject 类实现。但它是在 NSCopying 协议中声明的。 (这类似于您自己的类实现表视图委托方法的方式,但它们是表视图委托协议的一部分。)
  • @GregParker:我不同意。例如,在 Cocoa 中,您有时会遇到 NSProxy 的对象,它们不是 NSObject 类的实例,但确实实现了 NSObject 协议。
  • @Chuck:你确定吗?如果我查看NSCopying Protocol Reference,它说协议提供的唯一方法是copyWithZone:。此外,它还提供了指向NSObject Class Referencecopy 方法的链接:“这是采用NSCopying 协议的类的便捷方法。”
猜你喜欢
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-25
  • 2011-06-25
  • 2021-08-19
相关资源
最近更新 更多