2012-06-29 1 views
5

У меня есть куча простых NSManagedObject s Я создаю в единичном тесте. У них просто есть один атрибут name типа NSString *. Я всегда даю NSManagedObject то же самое имя entityName и Class.Как получить класс Objective-C для ivar?

Я хочу, чтобы избежать того, чтобы написать следующий код 30 раз, чтобы создать модульный тест:

@interface FooTest : GHTestCase { 
Foo *foo; 
} 
@end 
@implementation FooTest 

- (void) setUp { 
    [super setUp]; 

    foo = [NSEntityDescription insertNewObjectForEntityForName:@"Foo" 
             inManagedObjectContext:managedObjectContext]; 
    foo.name = @"foo"; 
} 
@end 

Поскольку foo является Ивар, я думаю, что я должен быть в состоянии написать макрос, чтобы захватить тип foo (Foo), а также использовать для создания моего Foo:

#define InsertManagedObjectByVariable(variable) \ 
do { \ 
variable = [NSEntityDescription insertNewObjectForEntityName:NSStringFromClass([typeof(variable) class])]; \ 
variable.name = (NSString *) CFSTR(#variable); 
} while(0) 

Однако, это вызывает следующее предупреждение в звоне:

variable = [NSEntityDescription insertNewObjectForEntityName:NSStringFromClass([typeof(variable) class])]; 
                      ^
                  Expected expression 

Я также думал, что я мог бы попытаться определить тип, используя Objective-C выполнения IVar от Ivar class_getInstanceVariable(Class cls, const char* name), но только информация IVar типа доступны из кодировки типа из ivar_getTypeEncoding является id, что не достаточно.

Может кто-нибудь подумать о способе получения информации о типе IVar либо во время компиляции, либо во время выполнения?

+1

Не тестировали это, не видя, компилирует ли он, но не можете ли вы сбросить 'typeof()' и пойти с '[variable class]'? –

+0

Нет, потому что 'variable' равно нулю. –

ответ

6

Я не пробовал получать информацию о классе из ivar, но я знаю, что объявления @property кодируют информацию о классе. Например, это свойство декларации:

@property (copy) NSString *normalString; 

результаты в этом атрибуте строки (извлеченной с помощью property_getAttributes()) во время выполнения:

[email protected]"NSString",C,VnormalString 

Я написал some open source parsing code эту информацию.

Как только у вас есть имя класса, вы можете преобразовать его в фактический объект класса с использованием NSClassFromString() и сообщить результат оттуда.

Отказ от ответственности: Это, вероятно, не должно зависеть для производственных приложений, так как оно недокументировано.

+0

Awesome. Я знал, когда я написал этот вопрос, чтобы вы знали ответ. :) –

+1

Очень интересный материал. Включение типа в виде строки не документировано; знаете ли вы, когда он был введен? –

+0

@RobNapier Хм, на самом деле не знаю. Он работает в Clang/Objective-C 2.0 до тех пор, пока я это пробовал. Вероятно, неплохо было зависеть от этого для производственного кода, но очень ценно для такого тестового решения. –

0

Возможно, я неправильно понимаю, чего вы пытаетесь достичь. Чтобы получить класс iVar, вы не можете использовать метод iVar?

нравится:

NSString *aString = @"random string"; 
NSLog(@"%@",NSStringFromClass([aString class])); 
+2

Не будет работать, если значение ivar равно нулю, как в случае с вопросом. –

5

id является id. Во время выполнения все объекты Objective-C имеют один и тот же тип (objc_object). Это связано с динамическим характером ObjC. Например, объект может изменять классы во время выполнения, создавать новые классы и изменять иерархию классов. Вы можете спросить конкретный экземпляр, каков его тип (поскольку он хранится в objc_object), но указатель на объект - это просто указатель на объект. Еще меньше: это действительно просто указатель на C-структуру, которая имеет дополнительную память, выделенную в конце (для хранения подкласса ivars).

Ваш макрос кажется интересным, но вам, вероятно, потребуется передать имя класса как второй параметр, а не автоопределять его.

+0

Спасибо. Да, я попытался описать это в своем вопросе. Я надеюсь, что кто-то с безумными навыками препроцессора C увидит это и выяснит, как превратить typeof() в выражение. –

Смежные вопросы