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 не является свойством. Как преобразовать его в имя переменной? Или как я могу установить свойство без создания бесконечного цикла?
Вы можете использовать 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
object_setIvar
не вызывая бесконечных циклов.