12

¿Hay algún medio de reflexión en Objective-C que le permita escribir implementaciones genéricas de NSCoding inspeccionando las propiedades públicas de un objeto y generando implementaciones genéricas de encodeWithCoder: e initWithCoder:.Objective-C Reflexión para implementación genérica de NSCoding

Estoy pensando en algo como XStream para Java que permite una forma genérica de serializar y deserializar objetos de Java utilizando la reflexión. Incluso mejor sería probablemente una forma de marcar las propiedades como cosas que desea serializar o que son transitorias (como la palabra clave transitoria en Java).

He estado leyendo la documentación en Archives and Serializations Programming Guide para Cocoa. Entiendo que quieres cierto control sobre la serialización de tus objetos, pero generalmente es un proceso simétrico y parece extraño tener que revertir lo codificado para la serialización para deserializarlo. Soy un creyente de SECO (no te repitas).

Respuesta

12

No solo es posible, sino que tengo un amigo que ha intentado precisamente eso. (Puede ver su blog about it here). La reflexión se realiza utilizando las funciones de tiempo de ejecución de Objective-C documentadas en el Objective-C 2.0 Runtime Reference. Echar un vistazo.

Tenga en cuenta, sin embargo, que esto solo funcionará si desea el comportamiento genérico de guardar todas las variables de instancia. Sin embargo, es posible que no desee que un NSView guarde su supervista; en tales casos, el caso genérico no funcionaría.

Podría distinguir entre cosas para serializar y cosas para no serializar al declarar propiedades para cualquier variable de instancia que desee guardar y dejar "otras variables" ocultas, pero eso está torciendo el propósito de las propiedades a un pequeño beneficio. No lo recomendaría.

6

(Soy el autor de la publicación del blog vinculada en el comentario de BJ Homer). Hay algunas advertencias sobre el uso del código:

  1. La clase objetivo debe ser compatible con KVC. Si está utilizando las propiedades de Objective-C 2.0 para sus ivars, entonces ya está todo listo. De lo contrario, debe asegurarse de que su clase esté configurada para responder adecuadamente a los métodos valueForKey: y setValue: forKey :.
  2. El código usa una "característica" no documentada del tiempo de ejecución para conformar recursivamente las clases de ivar a NSCoding. Cuando se compila, casi toda la información de tipeo (AFAIK) se elimina del código, sin embargo para guardar los ivars, ellos tienen que conformarse con NSCoding también. Descubrí que si el ivar es un objeto y lo llamo ivar_getTypeEncoding(), obtendré una cadena c que se parece a {{#IVAR_CLASS} (Ejemplo: {#NSString}). Lo que hago es obtener la cadena entre # y}, crear un objeto de Clase usando NSClassFromString y recurse en eso.
  3. Este código guardará TODOS los ivars.
  4. uso bajo su propio riesgo (por supuesto)

me escribió esto principalmente como una prueba de concepto, y hay muchos casos en los que el código fallaría espectacularmente. Por ejemplo, en el objeto A tiene un ivar para B, y B tiene un ivar para A, luego usar el código para serializar uno u otro (creo) causar un bucle infinito.

Sin embargo, creo que es bastante asombroso que Objective-C incluso te permita hacer cosas como esta en primer lugar.

0

Salida RMModelObject:

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

Sin embargo, cabe destacar que en tiempo de ejecución ObjC materia trabaja en el 10,5, y en el simulador, pero no en un iPhone real. Lo descubrí por el camino difícil. Tal vez OS 3.0 finalmente lo admite, pero no lo he comprobado.

Cuestiones relacionadas