@dynamicを自前で実装する

こんにちは ビンゴ中西です。

Objective-Cメタプログラミングを勉強中です。

Cora Dataを使っていると出てくる @dynamicこれは、
setterとgetterをどうやら実行時に作成するときに使われるみたい。

つまり、@dynamicはメタプログラミングでsetterとgetter作るよってことを示しているんですね。

やってみよう

Hoge.h

@property (nonatomic, retain) NSString *hoge;

Hoge.m

static Hoge* hogeSingle = nil;

- (id)init
{
    self = [super init];
    if (self) {
        void (^setBlock)(id o, NSString *s) = ^(id o, NSString *s){ NSLog(@">>> %@",s); };
        NSString *(^getBlock)(id o) = ^(id o){
            NSLog(@"%@", o);
            return @"Test";
        };
        SEL setSel = NSSelectorFromString(@"setHoge:");
        SEL getSel = NSSelectorFromString(@"hoge");
        IMP setImp = imp_implementationWithBlock(setBlock);
        IMP getImp = imp_implementationWithBlock(getBlock);
        class_addMethod([Hoge class], setSel, setImp, "v@:@");
        class_addMethod([Hoge class], getSel, getImp, "v@:");
    }
    return self;
}

// シングルトン
+(Hoge*)sharedManager{
    @synchronized(self) {
        if (hogeSingle == nil) {
            hogeSingle = [[self alloc] init];
        }
    }
    return hogeSingle;
}

imp_implementationWithBlockの第1引数には呼び出しもとのインスタンスが入るみたいです。
Perlでのオブジェクト指向と一緒ですね。Perlも関数でオブジェクト指向をするために、第1引数に呼び出したインスタンスをもらってますし。

使い方

[[Hoge sharedManager] setHoge:@"AA"];    // sharedManagerでシングルトンをゲットしています。
NSLog(@"%@", [Hoge sharedManager].hoge);

結果:

>>> AA
Test

それっぽく動いています。