6

プロトコルを定義しました。オプションとして、2 つのプロトコル メソッドについて言及しました。実行時に、特定のメソッドがオプションかどうかを確認するにはどうすればよいですか? それを知る方法はありますか?

4

2 に答える 2

12

これはあなたが望むことをするはずです:

BOOL MethodInProtocolIsRequired(Protocol *protocol, SEL methodSelector)
{
    struct objc_method_description methodDesc = protocol_getMethodDescription(protocol, methodSelector, YES, YES);
    return methodDesc.name != NULL;
}

特に、これを実行する理由を説明していないため、出荷コードでこれを使用することの妥当性についてはコメントしていません。また、プロトコルに含まれていないメソッドのセレクターが指定された場合、この関数はNOを返すことに注意してください。これは基本的に合理的です(結局のところ、プロトコルにメソッドが含まれていない場合は必須ではありません!)が、プロトコルにオプションのメソッドとしてメソッドが含まれているかどうかを確認し、別のメソッドを返すことで、関数に洗練を加えることができます。 3つのシナリオすべて(必須、オプション、プロトコル外)。

編集:ここの簡単なテストプログラム:https ://gist.github.com/4381753

于 2012-12-26T17:41:05.310 に答える
3

(頭のてっぺんから答えがわかりません。1分間のグーグルで助けてくれました。)

protocol_copyMethodDescriptionList()これは、Objective-Cランタイムライブラリ(libobjc)の一部である関数を使用して行うことができます。この関数の2番目の引数は、プロトコルでコピーされるメソッドが必要かどうかを示すブールフラグです。したがって、メソッドがこの関数によって返されるリストにある場合(適切な引数を使用して呼び出される)、それは必須のメソッドです。

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
}
于 2012-12-26T17:40:11.990 に答える