Динамическое создание геттеров и сеттеров для @dynamic свойств, вызывающих бесконечный цикл

0

Currenlty У меня проблема с ocmock для модульного тестирования, потому что некоторые @динамические свойства не имеют геттеров или сеттеров, когда их издеваются. Я использую class_addmethod для добавления геттеров и сеттеров для всех свойств @dynamic. Моя проблема в этом

void accessorSetter(id self, SEL _cmd, id newValue)
{
    NSString *method = NSStringFromSelector(_cmd);
    id value = [newValue copy];
// remove set prefix from string
    NSString *anID = [[method stringByReplacingCharactersInRange:NSMakeRange(0, 3) withString:@""] stringByReplacingOccurrencesOfString:@":" withString:@""];
    anID = [anID stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[anID substringWithRange:NSMakeRange(0, 1)] lowercaseString]];
    [self setValue:value forKey:anID];
}

вызывает инфинитные циклы, поскольку setValue вызывает setter. Я думаю, что я могу использовать синтаксис c++, например self->somevar = value чтобы избежать бесконечного цикла. Мой вопрос: как это сделать, когда имя переменной является строкой? anID - это имя переменной, и я не могу выполнить self->anID = aValue cuz anID не является свойством. Как преобразовать его в имя переменной? Или как я могу установить свойство без создания бесконечного цикла?

Теги:

1 ответ

0
Лучший ответ

Вы можете использовать object_setInstanceVariable или object_setIvar и object_getInstanceVariable. Для получения дополнительной информации вы можете взглянуть на ссылку Objective C Runtime Reference.

EDIT: Если вы используете ARC, вы не можете использовать object_setInstanceVariable. Вы будете застрять с object_setIvar.

EDIT 2: см. Этот ответ, если вы используете ARC.

Пример использования:

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

@interface Test : NSObject
@property (nonatomic, strong) NSString *test;
@end
@implementation Test
- (id)init {
    if (self = [super init]) {
    self.test = @"asdasd";
    }
    return self;
}
- (void)setTest:(NSString*)test {
    Ivar var_desc = object_getInstanceVariable(self, [@"_test" cStringUsingEncoding:NSUTF8StringEncoding], NULL);
    NSLog(@"Setting _test to %@", test);
    object_setIvar(self, var_desc, test);
}
@end

int main(int argc, char *argv[])
{
    Test *tst = [[Test alloc] init];
    NSLog(@"prop: %@", tst.test);
    return 0;
}

Вывод:

2013-12-11 18:19:32.038 ivar_tst[97090:507] Setting _test to asdasd
2013-12-11 18:19:32.040 ivar_tst[97090:507] prop: asdasd
  • 0
    Отличная идея. Все еще кажется, что вызывает бесконечный цикл. У меня есть методы ARC, но я могу видеть, используя точки останова, которые вызывают себя снова и снова. Не уверен, есть ли способ обойти это, но кажется, что вы не можете переопределить метод установки во время выполнения.
  • 0
    Ваша проблема определенно в другом месте ... посмотрите мой отредактированный ответ с примером, который переопределяет сеттер и использует object_setIvar не вызывая бесконечных циклов.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню