Geometry 関数
NSBundle
NSDictionary
NSFileManager
NSMutableAttributedString
NSNumber
NSScanner
NSString
NSTimer
Graphic 関数
NSApplication
NSBezierPath
NSCell
NSColor
NSCursor
NSCustomImageRep
NSDocument
NSDocumentController
NSDragging
NSEvent
NSFontManager
NSGraphicsContext
NSImage
NSMenu
NSOutlineView
NSPanel
NSPopUpButton
NSResponder
NSScrollView
NSString 追加
NSTableColumn
NSTableView
NSTextStorage
NSTextView
NSToolbar
NSView
NSWindow
NSWorkspace
その他
.nib ウィンドウ
Views パレット
クラス
-Class とは
-アプリケーションで使っているクラスをすべて取得する
-クラスを階層表示する
インスタンス変数
メソッド
CFXML
Carbon Event
Carbon Graphics
Cocoa で日本語
メソッド
その他

- Objective-C-
クラス

Objective-C - クラス
Class とは
Keywords: Class

Objective-C で、オブジェクトのクラスを表すのは Class 型。で、結局のところ、この Class 型って何なの?

順に追っていこう。まず、Class 型の定義は /usr/include/objc/obj.c にある。

/usr/include/objc/objc.h
typedef struct objc_class *Class;

つまり、Class 型は、構造体 objc_class のポインタだ。構造体 objc_class の定義は /usr/include/objc/objc-class.h にある。

/usr/include/objc/objc-class.h
struct objc_class {
    struct objc_class *isa;	
    struct objc_class *super_class;	
    const char *name;		
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;

    struct objc_method_list **methodLists;

    struct objc_cache *cache;
    struct objc_protocol_list *protocols;
};

これが、メモリ上に展開される、クラスの実体になるわけだ。含まれている情報は、

  • isa
    このクラスの isa ポインタ
  • super_class
    親クラス
  • name
    クラスの名前
  • version
    バージョン
  • instance_size
    インスタンスの大きさ
  • ivars
    インスタンス変数のリスト
  • methodLists
    メソッドリスト(複数)
  • protocols
    プロトコル

っていう感じだ。これで、Objective-C の実行環境に必要な情報が、ほぼそろうね。


Objective-C - クラス
アプリケーションで使っているクラスをすべて取得する
Keywords: objc_getClassList

あるアプリケーションで、Objective-C runtime が持っているすべてのクラスを取得してみよう。そのための、そのものずばりの関数がある。objc_getClassList() だ。/usr/include/objc/objc-runtime.h に定義がある。

/usr/include/objc/objc-runtime.h
OBJC_EXPORT int objc_getClassList(
        Class *buffer, 
        int bufferLen);

この関数を呼ぶときは、buffer に Class のポインタが入るバッファを、bufferLen にはその大きさを指定するんだ。返り値は、クラスの数が入る。

ヘッダ objc-runtime.h に、この関数の使い方が書いてある。まず、buffer に NULL を指定して呼んでやる。そうすると、返り値として、クラスの数が返ってくるんだ。そうしたら、その大きさだけのメモリを確保して、もう一回呼んでやるんだ。クラスの数が多すぎたら、何回かに分けて呼んでやる。

showAllClasse() (sample)
#import <objc/objc-runtime.h>

void showAllClasses {
    int numClasses = objc_getClassList(NULL, 0);
    int i;
    Class* classes;
    Class* tmp;
    
    classes = malloc(sizeof(Class) * numClasses);
    objc_getClassList(classes, numClasses);
    
    tmp = classes;
    for(i = 0; i < numClasses; i++) {
        printf("%s?", (*tmp++)->name);
    }
    
    free(classes);
}

上のコードが、すべてのクラスにアクセスするサンプルだ。取り出した後に、そいつらの名前を printf() で表示させているよ。


Objective-C - クラス
クラスを階層表示する
Keywords: objc_getClassList

すべてのクラスを取得したので、それを階層表示させてみよう。Class 型、すなわち objc_class 構造体には、super_class という親クラスへのポインタがあるんだ。

/usr/include/objc/objc-class.h
struct objc_class {
    ...
    struct objc_class *super_class;	
    ...
};

これをたどっていけば、階層構造を知ることができる。ルートクラスは、これが nil になってるよ。

階層構造を表示する、簡単なアプリケーションを作ってみた。実際に階層を調べるところは、こんな感じになっている。

ClassViewerControll.m (sample)
    // Get all classes
    classes = malloc(sizeof(Class) * numClasses);
    objc_getClassList(classes, numClasses);
    
    tmp = classes;
    for(i = 0; i < numClasses; i++) {
        // Get class name
        classNameStr = [NSString stringWithCString:(*tmp)->name];
        [_classNameArray addObject:classNameStr];
        
        // Get super class name
        if((*tmp)->super_class != nil) {
            NSMutableArray*	array;
            
            superNameStr = [NSString 
                stringWithCString:(*tmp)->super_class->name];
            
            array = [_classNameHierDict objectForKey:superNameStr];
            if(array == nil) {
                // Create new array
                array = [NSMutableArray array];
                [_classNameHierDict setObject:array forKey:superNameStr];
            }
            
            [array addObject:classNameStr];
        }
        else {
            // This class should be root
            [_classNameRootArray addObject:classNameStr];
        }
        
        tmp++;
    }
    
    free(classes);

最初に、すべてのクラスを取得する。そして、それを一個ずつ走査していくんだ。まず、そのクラスの名前を調べる。次に、親がいるかどうかを、super_class を見ることによって、調べるんだ。親がいる場合は、その親の名前を key にして、dictionary につっこむ。いない場合は、これはルートクラスなので、それ専用の array に入れてるんだ。

class viewer

これで、root の array からたどっていけば、階層構造を知ることができるんだ。試しに作ってみたアプリケーションの実行結果は、右のような感じ。

■サンプルダウンロード:
ClassViewer.tar.gz



[Home] [Download] [Archives] [BBS] [Cocoa Programming Tips 1001] [Core Foundation の秘密] [Safari Developer Center] [はじめてのブラウザのつくり方] [Sketch BP] [スクリーンセイバーを作ろう] [Objective-C 最適化] [Authorization API 完全理解] [Mac OS X Programming Books Review] [オブジェクト指向の言語比較論] [panther-dev]

mailto: mkino@xd5.so-net.ne.jp