2012-06-29 9 views
5

単体テストで作成するシンプルなNSManagedObjectの束を持っています。彼らはNSString *タイプの単一のname属性を持っています。私はいつも私のNSManagedObjectに同じentityNameClassという名前を与えます。Objective-Cクラスはどのようにして取得できますか?

私はユニットテストを設定するには、次のコードを30回書き込みすることを避けるためにしたい:

@interface FooTest : GHTestCase { 
Foo *foo; 
} 
@end 
@implementation FooTest 

- (void) setUp { 
    [super setUp]; 

    foo = [NSEntityDescription insertNewObjectForEntityForName:@"Foo" 
             inManagedObjectContext:managedObjectContext]; 
    foo.name = @"foo"; 
} 
@end 

fooがIVARですので、私は私がつかむためにマクロを記述することができるはずと思うだろうfooの種類(Foo)、そして私のFooを作成するために使用します。

#define InsertManagedObjectByVariable(variable) \ 
do { \ 
variable = [NSEntityDescription insertNewObjectForEntityName:NSStringFromClass([typeof(variable) class])]; \ 
variable.name = (NSString *) CFSTR(#variable); 
} while(0) 

しかし、これは打ち鳴らす中に次の警告が発生します

variable = [NSEntityDescription insertNewObjectForEntityName:NSStringFromClass([typeof(variable) class])]; 
                      ^
                  Expected expression 

私も、私はIvar class_getInstanceVariable(Class cls, const char* name)からObjective-CランタイムIVarを使用してタイプを決定しようと考えていたが、ivar_getTypeEncodingからタイプエンコーディングから入手できるだけIVar型情報が十分ではありませんこれは、idです。

誰かがコンパイル時または実行時にIVarの型情報を取得する方法を考えることができますか?

+1

これをコンパイルできるかどうかを確認した上でテストしたことはありませんが、 'typeof()'を削除して '[variable class]'にすることはできませんか? –

+0

いいえ、 'variable'がnilであるためです。 –

答えて

6

私はivarからクラス情報を取得しようとしませんでしたが、私は@property宣言がそのクラスに関する情報をエンコードしていることを知っています。たとえば、このプロパティ宣言:実行時に(property_getAttributes()を使用して取得した)この属性の文字列で

@property (copy) NSString *normalString; 

結果:

[email protected]"NSString",C,VnormalString 

私はこの情報をsome open source parsing codeを書きました。

クラス名を取得したら、NSClassFromString()を使用して実際のClassオブジェクトに変換し、その結果をメッセージで伝えることができます。

免責事項:これはドキュメント化されていないため、本番アプリケーションには依存していない可能性があります。

+0

素晴らしいです。私はこの質問を書いた時、答えを知っていることを知っていました。 :) –

+1

非常に面白いもの。文字列としての型のインクルードは文書化されていません。それがいつ紹介されたか知っていますか? –

+0

@RobNapierええと、本当に分かりません。私が試した限りClang/Objective-C 2.0で働いていました。おそらく、プロダクションコードに依存するのは良い考えではありませんが、このようなテストソリューションにとっては非常に貴重です。 –

0

多分あなたが達成しようとしていることを誤解しているかもしれません。 iVarのクラスを取得するには、クラス iVarのメソッドを使用できませんか?

のような:

NSString *aString = @"random string"; 
NSLog(@"%@",NSStringFromClass([aString class])); 
+2

質問の場合のように、ivarの値がnilであれば動作しません。 –

5

ididです。実行時に、すべてのObjective-Cオブジェクトのタイプが同じです(objc_object)。これはObjCの動的な性質に縛られています。たとえば、オブジェクトは実行時にクラスを変更したり、新しいクラスを作成したり、クラス階層を変更することができます。特定のインスタンスにその型を問い合わせることができます(これはobjc_objectに格納されているため)。オブジェクトへのポインタはオブジェクトへのポインタに過ぎません。これよりも少なくても、それは最後に(サブクラスivarsを保持するために)余分なメモリが割り当てられるC構造体へのポインタに過ぎません。

あなたのマクロは面白そうですが、おそらくクラス名を自動検出ではなく2番目のパラメータとして渡す必要があります。

+0

ありがとうございます。はい、私は私の質問でそれを概説しようとしました。私は狂ったCプリプロセッサのスキルを持つ誰かがこれを見て、typeof()を式にする方法を見つけてくれることを願っています。 –

関連する問題