2012-06-29 14 views
5

Mam kilka prostych NSManagedObject s tworzę w teście jednostkowym. Mają po prostu jeden atrybut name typu NSString *. Zawsze daję mojej NSManagedObject tę samą nazwę entityName i Class.Jak uzyskać klasę Objective-C dla ivar?

chcę uniknąć konieczności pisania następujący kod 30 razy, aby skonfigurować test Jednostka:

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

- (void) setUp { 
    [super setUp]; 

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

Od foo jest Ivar, to myślę, że powinienem być w stanie napisać makro chwycić rodzaj foo (Foo) i używać do tworzenia mojego Foo:

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

jednak to powoduje następujące ostrzeżenie w brzękiem:

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

Pomyślałem też mógłbym spróbować określić typ użyciem objective-c czas pracy IVar od Ivar class_getInstanceVariable(Class cls, const char* name), ale tylko informacja IVar typu dostępne z kodowaniem typu z ivar_getTypeEncoding jest id, co nie jest wystarczające.

Czy ktoś może wymyślić sposób uzyskania informacji o typie obiektu IVar w czasie kompilacji lub w czasie wykonywania?

+1

Nie testowałem tego poza sprawdzeniem, czy kompiluje, ale czy nie można upuścić 'typeof()' i iść z '[zmienna klasa]'? –

+0

Nie, ponieważ 'zmienna' jest zerowa. –

Odpowiedz

6

Nie próbowałem uzyskać informacji o klasie od ivar, ale wiem, że deklaracje @property kodują informacje o klasie. Na przykład, deklaracja ta właściwość:

@property (copy) NSString *normalString; 

wyniki w tym ciągu atrybutu (pobierane za pomocą property_getAttributes()) przy starcie:

[email protected]"NSString",C,VnormalString 

Pisałem some open source parsing code dla informacji.

Po utworzeniu nazwy klasy można przekonwertować ją na rzeczywisty obiekt klasy przy użyciu numeru NSClassFromString() i wysłać z niego wynik.

Nota prawna: To prawdopodobnie nie powinno być zależne od aplikacji produkcyjnych, ponieważ jest nieudokumentowane.

+0

Awesome. Kiedy napisałem to pytanie, wiedziałem, że znasz odpowiedź. :) –

+1

Bardzo interesujące rzeczy. Włączenie typu jako łańcucha nie jest udokumentowane; czy wiesz, kiedy został wprowadzony? –

+0

@RobNapier Hmm, naprawdę nie mam pojęcia. Pracuje w Clang/Objective-C 2.0 tak długo, jak próbowałem. Prawdopodobnie nie jest to dobry pomysł, aby polegać na nim na kod produkcyjny, ale bardzo cenny dla takiego rozwiązania testowego. –

0

Może źle rozumiem, co próbujesz osiągnąć. Aby uzyskać klasę iVar, nie można użyć metody klasy iVar klasy klasy?

lubię:

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

Nie będzie działać, jeśli wartość ivar ma wartość zerową, tak jak w pytaniu. –

5

id jest id. W czasie wykonywania wszystkie obiekty Objective-C mają ten sam typ (objc_object). Jest to związane z dynamiczną naturą ObjC. Na przykład obiekt może zmieniać klasy w środowisku wykonawczym, można tworzyć nowe klasy i zmieniać hierarchię klas. Możesz zapytać konkretną instancję o jej typ (ponieważ jest przechowywany w objc_object), ale wskaźnik do obiektu jest po prostu wskaźnikiem do obiektu. Nawet mniej niż: to tak naprawdę jest tylko wskaźnikiem do struktury C, która ma przypisaną dodatkową pamięć na końcu (do przechowywania podklas ivars).

Twoje makro wydaje się interesujące, ale prawdopodobnie będziesz musiał podać nazwę klasy jako drugi parametr zamiast automatycznego wykrywania.

+0

Dzięki. Tak, próbowałem opisać to w moim pytaniu. Mam nadzieję, że ktoś z szalonymi umiejętnościami preprocesora C zobaczy to i wymyśli, jak zmienić typof() w wyrażenie. –

Powiązane problemy