2012-01-10 13 views
4

実行時にプロパティの実装方法を追加したいと思います。追加私は+ resolveInstanceMethod、class_addMethodを使用します。しかし、dynamicN()とdynamicSetN()のコードの下ではコンパイルできず、合成プロパティなしでインスタンス変数を設定/取得するためのC-Functionの使い方がわかりません。動的プロパティgetter/setterの生成方法は?

#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

float dynamicN(id self, SEL _cmd) 
{ 
    NSString *methodName = NSStringFromSelector(_cmd); 
    NSLog(@"%@,%@", methodName, [self description]); 
    // return [self n]; 
} 

void dynamicSetN(id self, SEL _cmd, float sname) 
{ 
    printf("setName start;\n"); 
    // self.n = sname; 
} 


@interface bird : NSObject 
{ 
    int height; 
    float n; 
} 

@property float n; 
@property int height; 

@end 

@implementation bird 
@synthesize height = height; 
@dynamic n; 

- (id)init 
{ 
    if (self = [super init]) { 
     n = 1.0; 
     height = 3; 
    } 
    return self; 
} 

- (float) n { 
    return n; 
} 

+ (BOOL) resolveInstanceMethod:(SEL)aSEL 
{ 
    if (aSEL == @selector(n)) { 
     //class_addMethod([self class], aSEL, (IMP) dynamicN, "[email protected]:"); 
     //return YES; 
    } 
    if (aSEL == @selector(setN:)) { 
     class_addMethod([self class], aSEL, (IMP) dynamicSetN, "[email protected]:f"); 
     return YES; 
    } 
    return [super resolveInstanceMethod:aSEL]; 
} 
@end 

int main(int argc, const char *argv[]) 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    bird *aBird = [[bird alloc] init]; 
    aBird.n = 3; 
    printf("\n%f\n,%d", aBird.n, aBird.height); 
    [pool drain]; 
    return 0; 
} 
+0

コンパイラからのエラーメッセージを追加してください。 –

答えて

2

@ H2CO3はあなたのセッターについては正しいです。ダイナミックゲッターにも同じ基本的な問題があります。 idに存在しない[self n]に電話をかけようとしています。 そのため、コンパイルされません。 (@ H2CO3の注記では、エラーではなく警告が生成されますが、すべて-Werrorを使用していますか?)さらに重要なことに、たとえそれがあったとしても、これは無限ループになります。 self.n[self n]の呼び出しであり、この関数にディスパッチされます。

例をお探しの場合は、iOS 6 Programming Pushing the Limitsの第20章のコードをダウンロードできます。 Person.mPersonプロジェクトをご覧ください。第28章では、この種の機能を実装する方法について、さらに興味がある場合にはもっと多くの説明が含まれています。

ObjCでの適切な命名は非常に重要であることに注意してください。あなたのクラスはBirdでなく、birdでなければなりません。動的ディスパッチなどの高度な機能を試す前に、ネーミングの基礎を身に付けることが重要です。

2

あなたselfパラメータは、それ自体で「N」という名前のプロパティを持たないタイプの「ID」であるので、あなたのセッターはコンパイルされません。あなたはそれを間接参照し、その後、直接キャストすることをお勧めします:

((bird *)self)->n = sname; 

あなたのゲッターはしかし良いようだ、それはコンパイルできない理由を私は知りません。

+0

ゲッターはそれ自身を呼び出し、実行時には機能しません。戻り値を取得するには、セッターと同じフィールドアクセスが必要です。私はそれがどちらもコンパイルされない理由を見ることができません。 –

+0

タイプ "id"は構文的に "n"という名前のプロパティを持っていません。コンパイラは、実際に-nまたは-setN:メソッドに応答するかどうかを知りません(ダイナミズムの価格です) –

+0

(id) - 動的タイプのバインドの使用がC-Functionの静的タイプと異なるかどうか? objective-c法で静的型と動的型の間にいくつかの違いがありますか? –

関連する問題