2009-10-16 18 views
6

Mam klasy, który wygląda tak:#typedef i KVC w ObjC

@interface Properties : NSObject { 
@private 
    NSNumber* prop1; 
    NSNumberBool* prop2; 
    //etc 

gdzie NSNumberBool jest typedef:

// in MyApp_Prefix.pch 
typedef NSNumber NSNumberBool; 

Mam wszystkie wymagane oświadczenia i @synthesize do @property tworzą właściwości prop1 i prop2.

Wszystko zostało skompilowane i działało dobrze, dopóki nie próbowałem uzyskać dostępu do prop2 przez [myProperties valueForKey: @ "prop2"]. Daje mi to błąd "klasa nie jest zgodna z kluczem wartości". Jednak wiele podobnych połączeń działa dobrze:

myProperties.prop2; //works 
[myProperties prop2]; //works 
[myProperties valueForKey:@"prop1"]; //works 
[myProperties valueForKey:@"prop2"] // throws NSUnknownKeyException ?? 

Co tu się dzieje i jak mogę to naprawić?

Dzięki,

+1

Naprawdę dziwne, osobiście wpadłem w to samo.Również jeśli zrobisz "[myProperties respondsToSelector: @selector (prop2)], to zwraca również TAK – jjramos

Odpowiedz

1

To dość stary post, ale doszedłem do niego, szukając rozwiązania tego problemu, który jest ładnie rozwiązany przez dyrektywę Objective-C 2.0 @compatibility_alias. Pozwala to napisać:

@compatibility_alias NSNumber NSNumberBool; 

i mają alias utworzony dla NSNumber. KVO działa z tym doskonale.

W porównaniu z obecnie akceptowaną odpowiedzią ma to tę wielką zaletę, że jest bezpieczny w użyciu.

4

Od kompilacji przykład i wydawanie class-dump na to, że pojawi się typedef jest coraz przekształcony

struct NSNumber { 
    Class _field1; 
}; 

@interface Properties : NSObject 
{ 
    NSNumber *prop1; 
    struct NSNumber *prop2; 
} 

Zmiana typedef do tego wydaje się działać prawidłowo, choć być może nie dokładnie to, co chcesz.

#define NSNumberBool NSNumber 
+0

Dzięki. Dobre wyjaśnienie + przyzwoite obejście – tba

4

Podejrzewam, że jest to problem związany ze sposobem, w jaki typedef współdziała z metodą kodowania.

Wierzę, że typedef pozostaje czystym słowem kluczowym C i tak naprawdę działa tylko z "typami" Objective-C, zwykle dlatego, że są one zaimplementowane jako struktury.

W rezultacie, gdy wpiszesz NS NSumber do NSNumberBool, działa dobrze dla wywołań metod (i właściwości składni kropek), ale (zakładając, że moja teoria jest poprawna), łamie kodowanie, które nie może powiedzieć, że NSNumberBool i NSNumber są tego samego typu.

Będę zainteresowany, aby zobaczyć, co mówi ktoś, kto wie lepiej.

1

Podobny do odpowiedzi nall, również próbowałem zrzut klasy. Znalazłem interesujące, choć brzydkie rozwiązanie. Poniższy kod:

typedef NSNumber* NSNumberBoolPtr; 

@interface Test : NSObject { 
    NSNumber *real; 
    NSNumberBoolPtr poser; 
} 

klasy zrzuca do:

@interface Test : NSObject 
{ 
    NSNumber *real; 
    NSNumber *poser; 
} 

@end 

Ponownie, nie jest to dokładnie to, co chcesz, ale co można uzyskać czas kompilatora sprawdzania nie mając NSNumbers i NSNumberBools przenikania (co zakładam powód typedef na pierwszym miejscu).