12

Czy istnieje sposób na odbicie w Objective-C, który pozwoliłby na pisanie ogólnych implementacji NSCoding przez inspekcję publicznych właściwości obiektu i generowanie ogólnych implementacji encodeWithCoder: i initWithCoder:.Odbicie Objective-C dla ogólnej implementacji NSCode

Myślę o czymś takim, jak XStream dla Javy, która pozwala na ogólny sposób serializowania i deserializacji obiektów Java za pomocą odbicia. Jeszcze lepiej byłoby pewnymi sposobami oznaczania właściwości jako rzeczy, które chcesz serializować lub które są przejściowe (jak przejściowe słowo kluczowe w Javie).

Czytałem dokumentację Archives and Serializations Programming Guide dla kakao. Rozumiem, że chcesz mieć pewną kontrolę nad serializacją swoich obiektów, ale generalnie jest to proces symetryczny i wydaje się dziwne, że musisz odwrócić to, co jest zakodowane w celu serializacji, aby deserializować to. Jestem wierzący w DRY (nie powtarzaj się).

Odpowiedz

12

Nie tylko jest to możliwe, ale mam przyjaciela, który zrobił to w taki sposób. (Możesz zobaczyć jego blog about it here.) Odbicie odbywa się za pomocą funkcji wykonawczych Objective-C udokumentowanych w Objective-C 2.0 Runtime Reference. Spójrz.

Pamiętaj jednak, że działa to tylko wtedy, gdy chcesz zachować ogólne zachowanie wszystkich zmiennych instancji. Możesz jednak nie chcieć, aby NSView zapisywał swój superview; w takich przypadkach ogólny przypadek nie zadziałałby.

Można sobie wyobrazić rozróżnienie między serializacją rzeczy a serią non-to-serialize poprzez deklarowanie właściwości dla dowolnych zmiennych instancji, które chcemy zapisać, i pozostawienie jakichkolwiek innych zmiennych "ukrytych", ale to przekręca cały cel właściwości na niewielką korzyść. Nie polecałbym tego.

6

(Jestem autorem wpisu na blogu powiązanego z komentarzem BJ Homera). Istnieje kilka zastrzeżeń dotyczących używania kodu:

  1. Klasa docelowa musi być zgodna z KVC. Jeśli używasz właściwości Objective-C 2.0 dla twoich ivars, to wszystko gotowe. W przeciwnym razie musisz się upewnić, że twoja klasa jest skonfigurowana tak, aby odpowiednio reagować na valueForKey: i setValue: forKey: methods.
  2. Kod wykorzystuje nieudokumentowaną "funkcję" środowiska wykonawczego do rekursywnej zgodności klas ivar z NSCoding. Po skompilowaniu prawie wszystkie informacje dotyczące pisania (AFAIK) są usuwane z kodu, ale aby zapisać je, muszą być one również zgodne z NSCoding. Odkryłem, że jeśli ivar jest obiektem i nazywam go ivar_getTypeEncoding(), otrzymam ciąg znaków c, który wygląda mniej więcej tak: {#IVAR_CLASS} (Przykład: {#NSString}). To, co robię, to pobranie ciągu między znakami # i}, utworzenie obiektu klasy przy użyciu NSClassFromString i rekurencja w tym zakresie.
  3. Ten kod zapisze WSZYSTKIE ivars.
  4. Użyj na własne ryzyko (oczywiście)

Napisałem to głównie jako dowód koncepcji, i istnieje wiele przypadków, kiedy ten kod nie powiedzie się spektakularnie. Na przykład, w obiekcie A ma ivar dla B, a B ma ivar dla A, a następnie użycie kodu do serializacji jednego lub drugiego spowoduje (jak sądzę) nieskończoną pętlę.

Mimo wszystko uważam, że to naprawdę niesamowite, że Objective-C pozwala nawet na robienie rzeczy jak na pierwszym miejscu.

0

Wyjazd RMModelObject:

http://www.realmacforge.com/svn/trunk/RMModelObject/

jednak pamiętać, że ObjC Runtime rzeczy działa w 10,5, a w symulatorze, ale nie na rzeczywiste iPhone. Przekonałem się na własnej skórze. Może system operacyjny w wersji 3.0 w końcu go obsługuje, ale nie sprawdziłem.