我已经定义了我的协议。 我已经将我的协议方法中的两个标记为可选项。 在运行时,如何找出特定方法是否为可选项? 有没有办法找出来?
我已经定义了我的协议。 我已经将我的协议方法中的两个标记为可选项。 在运行时,如何找出特定方法是否为可选项? 有没有办法找出来?
BOOL MethodInProtocolIsRequired(Protocol *protocol, SEL methodSelector)
{
struct objc_method_description methodDesc = protocol_getMethodDescription(protocol, methodSelector, YES, YES);
return methodDesc.name != NULL;
}
请注意,我不评论使用此功能在运输代码中的可行性,尤其是因为您没有解释为什么要这样做。还要注意,当给出协议不包含方法的选择器时,该函数将返回NO。这基本上是合理的(毕竟,如果协议不包含方法,则不需要),但您可以通过检查协议是否将该方法作为可选方法包含并为所有三种情况(必需的、可选的、不在协议中)返回不同的内容来增加该函数的复杂性。编辑:简单测试程序在此处:https://gist.github.com/4381753
protocol_copyMethodDescriptionList()
函数实现此功能,该函数是Objective-C运行时库(libobjc)的一部分。该函数的第二个参数是一个布尔标志,指示要复制到协议中的方法是否为必需。因此,如果该函数返回的列表中包含一个方法(使用适当的参数调用),则该方法是必需的。SEL sctr = @selector(isThisMethod:requiredIn:theProtocol:);
struct objc_method_description *methods;
unsigned int nMethods;
methods = protocol_copyMethodDescriptionList(
objc_getProtocol("MyProtocolName"), // or @protocol(MyProtocolName) if you don't need this kind of dynamism
YES, // required?
YES, // instance method? (in general, protocols declare instance methods)
&nMethods
);
BOOL isRequired = NO;
int i;
SEL s;
const char *sctrStr = sel_getName(sctr);
for (i = 0; i < nMethods; i++) {
s = methods[i].name;
const char *sStr = sel_getName(s);
if (strcmp(sctrScr, sStr) == 0) {
isRequired = YES;
break;
}
}
free(methods);
if (isRequired) {
// required
} else {
// optional
}
所以,这是可能的,但有点过度设计了。正如我在你的问题评论中提到的那样,你不应该测试一个方法是否可选或必需,而应该测试一个实例是否响应特定的选择器。
编辑:是的,我应该阅读文档更深入一些,而不是复制整个宇宙。正如Andrew Madsen指出的那样,这可以简化为几行代码:
struct objc_method_description method;
method = protocol_getMethodDescription(
objc_getProtocol("MyProtocolName"), // or @protocol(MyProtocolName)
@selector(isThisSelector:required:)
YES, // required?
YES // instance method?
);
if (method.name != NULL) {
// required
} else {
// optional
}
bool
/_Bool
。 - Peter Hosey@selector
怎么比 #define
更不像 Objective-C 呢? - Nikolai Ruhe
respondsToSelector:
而不是假设必需的方法已经实现。 - user529758