当我尝试在id类型的对象上调用方法时,我收到警告(找不到方法)。我怎么称呼这个方法:
Class A *instanceACasted = (ClassA *)idvalue ;
然后调用方法
[instanceACasted methodCall];
这是一种方式,但我不知道使用id的类名称如何调用方法
答案 0 :(得分:1)
您可以使用内省和performSelector
:
SEL selector = @selector(yourMethodSignature:);
if ([obj respondsToSelector:selector]) {
[obj performSelector:selector];
}
关于how to use introspection的Apple文档。
答案 1 :(得分:0)
要消除警告method not found
,您必须将id
类型对象转换/转换为正确的对象类型。但在这种情况下,您需要知道Class
类型对象的id
名称。
如果您不知道班级名称,请遵循此answer。
答案 2 :(得分:0)
正确的答案在很大程度上取决于你实际在做什么。您的代码没有编译,并且找不到您的错误消息"方法"在Clang中不存在,所以我不知道实际发生了什么。此外,您的主题与我可能从您的代码中猜到的相矛盾(在您的代码中没有提及" id")。以下是一些猜测:
ObjC主要从上到下读取代码,并分别读取每个源文件(实现文件,.m文件,而不是标题),作为其自己的编译单元"。因此,如果您的源文件试图调用不在您文件中的方法,则会收到error: no known instance method for selector 'doSomething'
或error: no known class method for selector 'doSomething'
之类的错误消息。
要解决此问题,您需要#import
标头,该标头声明定义您要调用的方法的类/协议。
类方法以+开头,实例方法以 - 开头。它们是完全分开的。因此,如果使用+声明一个方法,然后在该类型的对象上调用它(而不是在myObject.class或类名称上),编译器可能会警告您error: no known instance method for selector 'doSomething'
resp。 error: no known class method for selector 'doSomething'
。这里重要的部分是它正在寻找一个类方法,即使存在实例方法,反之亦然。
在这种情况下,您会收到一个异常,它会将您反弹回运行循环并在运行时将发送给日志消息。这可能意味着您的代码期望一个较新的操作系统版本的类(具有该方法)但是在较旧的操作系统上运行(此方法尚未存在)。在这种情况下,您会收到unrecognized selector sent to instance 0x7fffdb13cf38
或unrecognized selector sent to class 0x7fffdb13cf38
等消息。
要解决这个问题,你可以通过询问一个对象[theObject respondsToSelector: @selector(doSomething)]
来检查一个对象是否响应给定方法,然后再调用它,否则做一些不依赖于该方法的东西。或者您可以提前检查该方法是否可用,只需隐藏按钮或那些在旧操作系统上需要的方法。
请注意,如果您有例如一个NSObject*
,你知道在一个特殊情况下它实际上可能是NSString*
,你使用-respondsToSelector:
来验证它是否实现了@selector(characterAtIndex:)
,在这种情况下,你仍然可以收到NSObject
个实例未响应-characterAtIndex:
的错误消息。在这种情况下,您可以通过执行以下操作来关闭该警告:
NSObject* myNSObject = myArray.firstObject;
if( [myNSObject respondsToSelector: @selector(characterAtIndex:)] )
[(NSString*)myNSObject characterAtIndex: 0];
或其他什么。但是,你通常不会写这样的代码。检查"我的对象是什么类"通常是你错误地构建了你的类层次结构的指示器,所以我只提到它的完整性'缘故。
您在标题中提及id
,但您的示例并未使用它。如果您在id
上调用方法,ObjC将允许您执行任何。它只需要在任何对象上的某个地方有给定方法的类或实例方法声明。在这种情况下,如果你调用给定对象没有的方法,它只会在运行时爆炸。