2011-07-31 10 views
7

NSBundleDidLoadNotificationでクラスの一覧をバンドルから取得できます。しかし、私はそれらがすでにロードされたバンドルからどのように得ることができるかを理解できません。 (コードと同じバンドル)特定のバンドル(またはバイナリ)のメモリにすでにロードされているクラスのリストを取得するにはどうすればよいですか?

私のアプリケーションバンドルのクラスリストを取得しようとしています。具体的には、私のアプリケーションバイナリのクラスだけです。

私はobjc_getClassListを見ましたが、それはALLクラスを返します。明らかに重すぎます。私は軽量のメソッドが必要です。私は、グーグルでobjc_copyClassNamesForImageを見つけましたが、文書化されていません。それを使用する方法がわかりません。安全に。私はそれを慣習的に使ってみることができると思うが、そこに行く前に別のより安全なオプションを探したい。

+0

あなたはもう少し問題空間を定義することはできますか?既にアプリケーション自体によってロードされているバンドルのクラスのリストを取得しようとしていますか? – NotMe

+0

@Chrisアプリケーションバイナリ自体で定義されたクラスリストを取得しようとしています。私は自分の質問を修正しました。ありがとう:) – Eonil

+0

あなたは次のドキュメントを見直しましたか? http://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFBundles/AccessingaBundlesContents/AccessingaBundlesContents.html – NotMe

答えて

1

ここでは、関数objc_copyClassNamesForImageのいくつかの例が見つかりました。

http://www.opensource.apple.com/source/objc4/objc4-493.9/test/weak.m

// class name list 
const char *image = class_getImageName(objc_getClass("NotMissingRoot")); 
testassert(image); 
const char **names = objc_copyClassNamesForImage(image, NULL); 
testassert(names); 
testassert(classInNameList(names, "NotMissingRoot")); 
testassert(classInNameList(names, "NotMissingSuper")); 
if (weakMissing) { 
    testassert(! classInNameList(names, "MissingRoot")); 
    testassert(! classInNameList(names, "MissingSuper")); 
} else { 
    testassert(classInNameList(names, "MissingRoot")); 
    testassert(classInNameList(names, "MissingSuper")); 
} 
free(names); 

ソースコードは、非公式しかし、Appleからです。だから私はこのコードを使用することにしました。

4

もう1つの選択肢は、ランタイムに登録されているすべてのクラスを反復して、どれが来たか把握するために、それぞれに+[NSBundle bundleForClass:]を使用することです。その結果に基づいて物をセットにソートすることができます。

@interface NSBundle (DDAdditions) 

- (NSArray *)definedClasses_dd; 

@end 

@implementation NSBundle (DDAdditions) 

- (NSArray *)definedClasses_dd { 
    NSMutableArray *array = [NSMutableArray array]; 

    int numberOfClasses = objc_getClassList(NULL, 0); 
    Class *classes = calloc(sizeof(Class), numberOfClasses); 
    numberOfClasses = objc_getClassList(classes, numberOfClasses); 
    for (int i = 0; i < numberOfClasses; ++i) { 
     Class c = classes[i]; 
     if ([NSBundle bundleForClass:c] == self) { 
      [array addObject:c]; 
     } 
    } 
    free(classes); 
    return array; 
} 

@end 

次にあなたが呼び出すことができます:このような

何か

NSLog(@"%@", [[NSBundle mainBundle] definedClasses_dd]); 
+0

現在システムにロードされているすべてのクラスを収集しているように見えます。私はそれを使用するときのパフォーマンスを考慮する必要がありますか? – Eonil

+0

@パフォーマンスを考慮できることを確認してください。これはiOS向けなので、他のバンドルをロードすることはないので、このコードを変更して見つけたバンドルごとに配列を作成し、それらの配列を静的情報としてキャッシュすることができます。次に、 'definedClasses'メソッドは単にそのキャッシュにアクセスします(または必要に応じて作成します)。 –

+0

あなたはポイントを見逃しました。彼は重くはない方法で達成したいと言いました。彼は特に重いobjc_getClassListメソッドを参照していました。それは途中で6000クラスを返します。 – malhal

4

はこの魔法を試してみてください:

-(NSArray*)getClassNames{ 
    NSMutableArray* classNames = [NSMutableArray array]; 
    unsigned int count = 0; 
    const char** classes = objc_copyClassNamesForImage([[[NSBundle mainBundle] executablePath] UTF8String], &count); 
    for(unsigned int i=0;i<count;i++){ 
     NSString* className = [NSString stringWithUTF8String:classes[i]]; 
     [classNames addObject:className]; 
    } 
    return classNames; 
} 
関連する問題