2010-11-22 8 views
3

私はObjective-CでiPhoneで作業しており、 'Class'が 'NSObject'から継承するかどうかを知る必要があります。 ...それもの「respondsToSelector:」応答しなかったクラスがNSObjectから継承するかどうかを確認する方法(Objective-C)

bool success = [myClass respondsToSelector:@selector(class)]; 

しかし、あなたは何が起こったのかを推測することができます:それは「実装されていませんスローので

は、私はそれがNSObjectのセレクタに応答するかどうかをチェックしてみましたdoesNotRecognizeSelector: "例外です。

私はその例外をキャッチしようとしましたが、@ try- @ catchでキャッチできないようです。

アイデア?

+2

私はより良い質問は、あなたがいないこれらのクラスに対処されるようになってきた方法だと思いますNSObjectから継承します。プロトコル以外には何もあってはいけません。 – Chuck

+1

@Chuckと 'NSProxy'です。 –

+0

'@selector(class)'を意味します。私は '+ class:'に応答するSDKには何もないと思う。 –

答えて

7

は、Objective-Cランタイムに直接移動しますクラスごとにisaポインタは、構造体objc_objectに確実にある唯一のものです。

編集:さらに、iPhoneシミュレータにはtry/catchブロックで捕捉されない例外がいくつかあるという既知のバグがあります。私は彼らをAppleにバグとして報告し、私は重複していると言われているので、彼らは間違いなく認識している。実際のデバイスやシミュレータのコードを試しましたか?

EDIT2:この会話の他の場所で与えられ、より広い文脈から、このようなものは賢くかもしれない:

#import <objc/runtime.h> 

BOOL classRespondsToSelector(Class classA, SEL selector) 
{ 
    return class_getInstanceMethod(classA, selector) ? YES : NO; 
} 

.... 
if(classRespondsToSelector(instance->isa, @selector(respondsToSelector:)) 
{ 
    // great, we've got something that responds to respondsToSelector:; do the 
    // rest of our querying through there 
} 
+0

この回答は優れており、完璧です。シミュレータ/デバイス上のtry/catchブロックについても正しいです。私はtry/catchブロックが(obj-cで)フローを制御するために使用されるべきではなく、シミュレータのデバッグを失うつもりはないので、この 'getSuperclass'コンセプトに固執します。 – bendytree

+0

実際にはそれほど正しくありません。 NSObjectのisaポインタがNSObjectを指している(つまり、NSObjectメタクラス自体もNSObjectのサブクラスである)が、NSObjectはそれ自身のスーパークラスではない。だから(classA == superClass)は、classDescendsFromClassを必要以上に後で終了させます(最終的にnilのスーパークラスとしてnilを取得するため)。コードを修正します。 – Tommy

+1

もっとObj-Cのような構文が好きな人は:https://gist.github.com/BillinghamJ/6709374 –

4

isKindOfClass:およびisMemberOfClass:のメソッドを使用して、あるクラスが別のクラスのサブクラスか、それが特定のクラスかどうかを判断できます。

+4

これらのメソッドは、NSObjectプロトコルの一部です。 NSObjectプロトコルに準拠していないオブジェクトは、これらのメッセージに応答しないことがあります。 – Greg

+0

真実ですが、誰もが言っているように、NSObjectプロトコルに準拠していないオブジェクトを扱うのはなぜですか?これはもっと重要な問題です。このプロトコルに準拠していないオブジェクトを持たない理由はありません。 – Jasarien

+1

Classオブジェクトを調べている場合はどうなりますか? –

1

respondsToSelector:自体はNSObject定義のセレクタなので、使用できません。私はObjective-Cの内部に深く入り込むことなくこれを行う方法があるとは思わない。

なぜNSObjectの子孫でないオブジェクトがあるのか​​尋ねることができますか?アップルはあなたがそれらを作成しようとしないことを強くお勧めします。

+2

実際、NSProxyはNSObjectから継承しないAppleが提供するクラスです。しかし、より重要なNSObjectプロトコルに準拠しています。 – cobbal

+0

NSObjectで定義されているすべてのものにすべてが応答すると想定するのはかなり安全です。 NSProxyはそうではありませんが、「実際の」オブジェクトには期待されます。 –

-3

クラス 'クラス'はNSObjectから継承しません。つまり、NSObjectで定義されたメソッド(isKindOfClassrespondsToSelectorなど)は使用できません。

最初に何をしようとしていますか?

#import <objc/runtime.h> 

/* originally posted version — works because eventually class_getSuperclass(class) 
returns nil, and class_getSuperclass(nil) does so also. */ 
BOOL classDescendsFromClass(Class classA, Class classB) 
{ 
    while(1) 
    { 
     if(classA == classB) return YES; 
     id superClass = class_getSuperclass(classA); 
     if(classA == superClass) return (superClass == classB); 
     classA = superClass; 
    } 
} 

/* shorter version; exits straight after classA turns into nil */ 
BOOL classDescendsFromClassShorter(Class classA, Class classB) 
{ 
    while(classA) 
    { 
     if(classA == classB) return YES; 
     classA = class_getSuperclass(classA); 
    } 

    return NO; 
} 
... 

if(classDescendsFromClass(classToTest->isa, [NSObject class]) ... 

class_getSuperclassは、それが言うことありません、それはメタクラスのだけ正確に一つのインスタンスがあるので、Objective-Cランタイムでのポインタでメタクラスを比較しても安全です:

+0

-1です。 「クラス」は、メタクラスのインスタンスである。 -NSObjectはスーパークラスが-NSObjectである+ NSObjectのインスタンスです。したがって、-NSObjectは-NSObjectのインスタンスです。私はどのメタクラスがインスタンスであるかはわかりません(おそらくNSObject!)、あるいは別のルートクラス(NSObjectから継承しない場合)を使用するとどうなりますか?しかし、メタクラスはクラスメソッドの基礎です「自己」を持たない静的メソッドへ)。 –

+1

-1 'Class'クラスはありません – user102008

関連する問題