12

C'è qualche mezzo di riflessione in Objective-C che consentirebbe di scrivere implementazioni NSCoding generiche ispezionando le proprietà pubbliche di un oggetto e generando implementazioni generiche di encodeWithCoder: e initWithCoder:.Riflesso Objective-C per un'implementazione generica NSCoding

Sto pensando a qualcosa come XStream per Java che consente un modo generico di serializzare e deserializzare oggetti Java utilizzando la reflection. Ancora meglio sarebbe probabilmente un modo di marcare le proprietà come le cose che si vorrebbe serializzare o che sono transitorie (come la parola chiave transitoria in Java).

Ho letto la documentazione su Archives and Serializations Programming Guide per Cocoa. Capisco che tu voglia controllare la serializzazione dei tuoi oggetti, ma in genere è un processo simmetrico e sembra strano dover invertire ciò che è codificato per la serializzazione per deserializzarlo. Sono un credente di ASCIUTTO (non ripeterti).

risposta

12

Non solo è possibile, ma ho un amico che ha preso una pugnalata nel fare esattamente questo. (È possibile vedere il suo blog about it here.) Il riflesso viene eseguito utilizzando le funzioni di runtime Objective-C documentate nello Objective-C 2.0 Runtime Reference. Guarda.

Si noti, tuttavia, che questo funzionerà solo se si desidera il comportamento generico di salvare tutte le variabili di istanza. Potresti non volere un NSView per salvare la sua superview, però; in questi casi, il caso generico non funzionerebbe.

È possibile distinguere tra cose da serializzare e cose da non serializzare dichiarando le proprietà per tutte le variabili di istanza che si desidera salvare e lasciando "nascoste" eventuali altre variabili, ma ciò sta distorcendo l'intero scopo delle proprietà con un piccolo vantaggio. Non lo raccomanderei.

6

(Sono l'autore del post sul blog collegato a nel commento di BJ Homer). Ci sono un paio di avvertenze per usare il codice:

  1. La classe di destinazione deve essere conforme a KVC. Se stai usando le proprietà di Objective-C 2.0 per i tuoi ivars, allora tutto è pronto. Altrimenti, è necessario assicurarsi che la classe sia impostata per rispondere correttamente a valueForKey: e setValue: forKey: metodi.
  2. Il codice utilizza una "funzione" non documentata del runtime per conformare ricorsivamente le classi ivar a NSCoding. Quando vengono compilate, quasi tutte le informazioni di digitazione (AFAIK) vengono rimosse dal codice, tuttavia per salvare gli ivars, , esse devono essere conformi a NSCoding anche da. Ho scoperto che se ivar è un oggetto e chiamo ivar_getTypeEncoding() su di esso, otterrò una stringa c che assomiglia a qualcosa: {#IVAR_CLASS} (Esempio: {#NSString}). Quello che faccio è ottenere la stringa tra il # e il}, creare un oggetto Class usando NSClassFromString e ricorrere su questo.
  3. Questo codice salverà TUTTI i ivars.
  4. Utilizzare a proprio rischio (ovviamente)

Ho scritto questo principalmente come una prova di concetto, e ci sono molti casi in cui questo codice sarebbe fallire spettacolare. Ad esempio, nell'oggetto A ha un ivar per B, e B ha un ivar per A, quindi usare il codice per serializzare l'uno o l'altro (credo) causa un ciclo infinito.

Tuttavia, penso che sia davvero fantastico vedere che Objective-C ti permette anche di fare cose come in primo luogo.

0

Partenza RMModelObject:

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

Si noti tuttavia che roba objC Runtime lavora a 10,5, e nel simulatore, ma non su un iPhone vero e proprio. Trovato fuori nel modo più duro ... Forse OS 3.0 finalmente lo supporta, ma non ho controllato.