如何生成动态属性getter / setter?

时间:2012-01-10 16:43:36

标签: objective-c

我想在运行时添加属性实现方法。添加我使用+ resolveInstanceMethod,class_addMethod来做。但是在代码下面,在dynamicN()和dynamicSetN()中,它们无法编译,我不知道如何在没有synthesize属性的情况下使用C-Function来设置/获取实例变量。

#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, "f@:");
        //return YES;
    }
    if (aSEL == @selector(setN:)) {
        class_addMethod([self class], aSEL, (IMP) dynamicSetN, "v@: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;
}

2 个答案:

答案 0 :(得分:2)

您的setter将无法编译,因为您的self参数的类型为“id”,它本身没有名为“n”的属性。你会想要直接取消引用它:

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

你的getter似乎很好,我不知道为什么它不能被编译。

答案 1 :(得分:2)

@ H2CO3对你的二传手是正确的。动态吸气器具有相同的基本问题。您正在尝试拨打[self n]id上不存在-Werror这就是为什么它不能编译。(正如@ H2CO3所说,这会产生警告,而不是错误;你们都在使用self.n,对吗?)但更重要的是,甚至如果确实如此,这将是一个无限循环。 [self n]只是对Person的调用,它将调度回此函数。

如果您正在寻找示例,可以下载iOS 6 Programming Pushing the Limits第20章的代码。查看Person.m项目Bird。如果您有兴趣,第28章将详细介绍如何实现此类功能。

请注意,ObjC中的正确命名非常重要。您的课程应该是bird,而不是{{1}}。在尝试动态调度等高级功能之前,掌握命名基础是至关重要的。