2014-06-09 6 views
12

Kiedy jestem wdrażania protokołu NSCoding w Objective-C, chciałbym użyć NSStringFromSelector(@selector(name)) aby dostać klucz ścieżkę nieruchomości, jak poniżejczasie kompilacji klucz ścieżka odprawy Swift

- (void)encodeWithCoder:(NSCoder *)aCoder { 
    [aCoder encodeObject:self.accountName forKey:NSStringFromSelector(@selector(accountName))]; 
    [aCoder encodeObject:self.userId forKey:NSStringFromSelector(@selector(userId))]; 
} 

- (id)initWithCoder:(NSCoder *)aDecoder { 
    self = [super init]; 
    if (self) { 
     _accountName = [aDecoder decodeObjectForKey:forKey:NSStringFromSelector(@selector(accountName))]; 
     _userId = [aDecoder decodeObjectForKey:forKey:NSStringFromSelector(@selector(userId))]; 
    } 
    return self; 
} 

Lubię to sposób, ponieważ zapobiega błędnemu wpisywaniu bez potrzeby definiowania partii stałych łańcuchowych, a otrzymam ostrzeżenia, jeśli zmienię nazwę tych właściwości. Ale nie mogłem znaleźć sposobu na zrobienie tego w Swift, żadnych pomysłów?

+0

czekać na refleksji API –

Odpowiedz

1

W Swift selektory są ciągami. (No cóż, istnieje typ Selector, ale w sposób przezroczysty konwertuje się do i od String.) Można więc pominąć NSStringFromSelector i @selector i użyć po prostu ciągu literowego.

Jeśli szukasz introspekcji nazw swoich nieruchomości ... to jest nieco trudniejsze. Użycie klasy reflect() dla instancji klasy zwraca obiekt typu Mirror. (Wklej jeden z tych symboli na swoim placu zabaw i kliknij cmd, aby uzyskać deklaracje w standardowej bibliotece "header".) Możesz użyć tego do przejścia na listę właściwości klasy.

W ten sposób metoda „zakodować wszystko” wyglądać tak:

func encodeWithCoder(coder: NSCoder!) { 
    let mirror = reflect(self) 
    let (accountNameKey, _) = mirror[0] 
    let (userIdKey, _) = mirror[1] 

    coder.encodeObject(accountName, forKey: accountNameKey) 
    coder.encodeObject(userId, forKey: userIdKey) 
} 

To nie jest idealny, ponieważ trzeba znać kolejność definicji właściwości. Ale może być poprawiony po ...

+8

Problem polega na tym, że do weryfikacji konieczna jest składnia '@selector()'. Jeśli po prostu włoży sznurki, może mieć literówkę i nie będzie miał ostrzeżenia. –

+0

Prawdziwym problemem jest szybka nie ma bezpośredniego zastąpienia tego zachowania jeszcze. –

+1

Począwszy od wersji 2.2, możesz użyć specjalnej składni dla uzyskania selektora. Na przykład 'let sel = #selector (UIView.insertSubview (_: at :)) // tworzy Selektor" insertSubview: atIndex: "'. Odsyłacz: https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md – Mrwerdo