Iphone 名为'的多个方法;标签';建立

Iphone 名为'的多个方法;标签';建立,iphone,objective-c,ios,xcode,Iphone,Objective C,Ios,Xcode,为什么我在下面的代码中收到此警告: - (IBAction)shareThisActionSheet:(id)sender { int row = [sender tag]; //warning is here! Multiple methods named 'tag' found ... 问题是发送者被定义为(id)对象。在编译时,xcode不知道将传递给函数的对象类型 如果为特定对象类型编写此函数,则可以编写 - (IBAction)shareThisActionSheet

为什么我在下面的代码中收到此警告:

- (IBAction)shareThisActionSheet:(id)sender
{
    int row = [sender tag]; //warning is here! Multiple methods named 'tag' found
    ...

问题是
发送者
被定义为
(id)
对象。在编译时,xcode不知道将传递给函数的对象类型

如果为特定对象类型编写此函数,则可以编写

- (IBAction)shareThisActionSheet:(UIButton*)sender
或者,您可以通过调用提示编译器对象的类型

int row = [(UIButton*)sender tag]; 

说明

问题是编译器在当前翻译单元中看到多个名为
tag
的方法,并且这些声明具有不同的返回类型。一个可能是
-[UIView tag]
,它返回一个
NSInteger
。但它也看到了另一个
标签的声明,也许:

@interface MONDate
- (NSString *)tag;
@end
然后编译器会发现一个歧义-是
sender
a
UIView
?或者是星期一

编译器警告您必须猜测
发送方的类型。这实际上是在要求未定义的行为

分辨率

如果您知道参数的类型,请指定它:

- (IBAction)shareThisActionSheet:(id)sender
{
 UIView * senderView = sender;
 int row = [senderView tag];
 ...

否则,使用诸如
isKindOfClass:
条件之类的条件来确定在发送消息之前声明变量的类型。正如其他答案所示,您也可以打字。巴斯蒂安是对的,您应该将发件人转换为如下按钮:

UIButton * button = (UIButton *)sender;
int row = button.tag;

如果你认为我是对的,为什么你要发布相同的答案而不是我的?因为我发布了一个不同的发送者类型(我认为它更正确,因为它更直观)使用
long row=[senderView tag]+1解释得很好。尽管有警告,但它在任何情况下都应该工作(使用id)。。对吗?@Ankit它不会起作用(参考:它要求的是未定义的行为)。如果所有可见的
tag
方法都返回一个objc对象,这是可预测的。如果一个返回一个
CGRect
,另一个返回一个objc对象,编译器可能会调用错误的
objc\u msgSend
变量,您可能会破坏堆栈的一部分。如果编译器以另一种方式猜测错误,
CGRect
可能会作为objc对象发送消息。你也可以切片内存,如果C++在那里,它甚至更复杂。(cont)(cont)另一种方法是查看生成的装配,针对生成的每个警告。更糟的是什么?如果未在TU中包含作为
发送方传递的对象类型,则可能不会收到警告。此警告有效。谢谢你的解释。我只是将它转换为UIButton而不是UIView。运行时不应该知道id的实际类,所以要使用正确的
标记
方法吗?我的意思是,当ClassB派生自ClassA,并且两者都有一个名为
tag
的方法时,当调用
ClassA
ClassB
的实例时,不应该调用相应的方法吗?或者问题出现在返回类型中?使用
long row=[senderView tag]