Как сгенерировать динамическое свойство getter / setter? - PullRequest
4 голосов
/ 10 января 2012

Я хочу добавить метод реализации свойства во время выполнения.Добавить Я использую + resolInstanceMethod, class_addMethod, чтобы сделать.Но ниже кода, в dynamicN () и dynamicSetN (), они не могут быть скомпилированы, и я не знаю, как использовать C-функцию для установки / получения переменной экземпляра без свойства синтеза.

#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 ]

2 голосов
/ 10 января 2012

@ H2CO3 правильно о вашем сеттере.Динамический геттер имеет ту же основную проблему.Вы пытаетесь позвонить [self n], которого нет на id. Вот почему он не скомпилируется. (Как отмечает @ H2CO3, это сгенерирует предупреждение, а не ошибку; вы все используете -Werror, верно?) Но что более важно, даже если он это сделалэто был бы бесконечный цикл.self.n - это просто вызов [self n], который отправит обратно к этой функции.

Если вы ищете примеры, вы можете скачать код для главы 20 Программирование на iOS 6 НажатиеОграничения .Посмотрите в проекте Person на Person.m.Глава 28 содержит гораздо больше объяснений о том, как реализовать такую ​​функцию, если вам интересно.

Обратите внимание, что правильное именование в ObjC очень важно.Ваш класс должен быть Bird, а не bird.Прежде чем пытаться использовать расширенные функции, такие как динамическая диспетчеризация, очень важно получить основы именования.

2 голосов
/ 10 января 2012

Ваш установщик не будет компилироваться, потому что ваш параметр self имеет тип "id", который сам по себе не имеет свойства с именем "n". Вы хотите разыграть, а затем разыменовать его:

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

Хотя ваш геттер выглядит неплохо, я не знаю, почему его нельзя скомпилировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...