Pregunta resumen:

Considerar una clase SyncObject que es KVC-compatible con propiedades tales como: time, someValue, lastChange, uuid.

Considerar un NSArray que contiene exclusivamente los casos de SyncObject.

Tengo que presentar la matriz para el servidor como un array de JSON.

¿Cómo se podía presentar esta matriz para el servidor mediante HTTP POST con RestKit?

Ejemplo de matriz:

[
  {
    "time": "14:45 10/21/2011",
    "someValue": "15",
    "lastChange": "14:45 10/21/2011",
    "uuid": "0b07c510-f4c8-11e0-be50-0800200c9a66"
  },
  {
    "time": "14:50 10/21/2011",
    "someValue": "62",
    "lastChange": "14:51 10/21/2011",
    "uuid": "1a6d4480-f4c8-11e0-be50-0800200c9a66"
  }
]

Detalles

Tengo un array de objetos que necesito para el servidor como JSON. A mí me parece que RestKit es la manera más fácil de hacer esto: estoy tratando de evitar la conversión de los objetos en un conjunto de NSDictionary objetos y, a continuación, el uso de algunos JSON encoder para obtener JSON que puedo POST para el servidor.

Así que, después de haber creado la matriz, y habiendo establecido la asignación para la clase de objetos almacenados en la matriz, yo, naturalmente, tratar de POST para el servidor.

RKObjectManager* mgr = [RKObjectManager objectManagerWithBaseURL:@"http://localhost/someweb/api/"];
mgr.serializationMIMEType = RKMIMETypeFormURLEncoded;
mgr.client.username = @"username";
mgr.client.password = @"password";
RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping mapKeyPath: @"time"       toAttribute:@"time"         ];  
[mapping mapKeyPath: @"someValue"  toAttribute:@"someValue"    ];
[mapping mapKeyPath: @"lastChange" toAttribute:@"lastChange"   ];
[mapping mapKeyPath: @"uuid"       toAttribute:@"uuid"         ];
RKObjectMapping* mappingForSerialization = [mapping inverseMapping];
[mgr.mappingProvider setSerializationMapping:mappingForSerialization 
                                    forClass:[NSManagedObject class]];

[mgr.router routeClass:[NSManagedObject class] toResourcePath:@"/sync" forMethod:RKRequestMethodPOST];    

[mgr postObject:array delegate:nil/*self*/];

Sin embargo, esto es lo que yo saco:

2011-10-11 14:57:51.769 AppConnect[1974:6e0b] *** Terminación de la aplicación debido a uncaught exception '(null)', la razón: "no se puede encontrar un enrutable ruta de acceso para un objeto de tipo '__NSArrayI' para el Método HTTP POST" 

Al parecer, RestKit no sabe cómo manejar NSArrays.

¿Cómo publicar un array de objetos utilizando RestKit?


He intentado algo diferente: que sustituyó a la última línea con un manual de enviar a través de RKObjectLoader.

//[mgr postObject:[NSMutableDictionary dictionaryWithObject:array forKey:@"data"] delegate:nil/*self*/];


NSString* syncPath = @"/sync"; 
RKObjectLoader * objectLoader = [mgr objectLoaderWithResourcePath:syncPath delegate:self];
objectLoader.serializationMIMEType = RKMIMETypeJSON;
objectLoader.method = RKRequestMethodPOST;
//objectLoader.objectClass = [NSManagedObject class];       
//objectLoader.managedObjectStore = mgr.objectStore; 
objectLoader.params = [NSDictionary dictionaryWithObject:array 
                                                  forKey:@"MyData"]; 
[objectLoader send];

Por desgracia, esto no se aplica la asignación de cualquier tipo, y en lugar transmite una matriz de objetos descripciones. Configuración de serializationMIMEType también no afectan a la estructura de transmisión de contenidos, y params son siempre transmitidos como application/x-www-form-urlencoded.

También probé la asignación de la serialización de asignación y pasar el objeto como targetObject y sourceObject (esto parece ser lo que RestKit hace internamente en -[RKObjectManager postObject:delegate:]).

RKObjectLoader * objectLoader = [mgr objectLoaderWithResourcePath:syncPath delegate:self];
objectLoader.method = RKRequestMethodPOST;
//objectLoader.objectClass = [NSManagedObject class];       
//objectLoader.managedObjectStore = mgr.objectStore; 
objectLoader.params = [NSMutableDictionary dictionaryWithObject:array 
                                                  forKey:@"MyData"]; 
objectLoader.serializationMapping = mapping;
objectLoader.serializationMIMEType = RKMIMETypeJSON;
objectLoader.sourceObject = objectLoader.params;
objectLoader.targetObject = objectLoader.params;
[objectLoader send];

Lamentablemente, no hay asignación se produce de esta manera:

2011-10-12 12:36:48.143 MyProject[5119:207] D restkit.network:RKObjectLoader.m:290 POST or PUT request for source object {
MyData =     (
"<NSManagedObject: 0x5935430> (entity: SomeRecord; id: 0x5934da0 <x-coredata://64DF9977-DA50-4FCD-8C20-4132E58439BF/SomeRecord/p1> ; data: <fault>)",
"<NSManagedObject: 0x5935730> (entity: SomeRecord; id: 0x5934db0 <x-coredata://64DF9977-DA50-4FCD-8C20-4132E58439BF/SomeRecord/p2> ; data: <fault>)"
);
}, serializing to MIME Type application/json for transport...
2011-10-12 12:36:48.143 MyProject[5119:207] D restkit.object_mapping:RKObjectMappingOperation.m:428 Starting mapping operation...
2011-10-12 12:36:48.145 MyProject[5119:207] T restkit.object_mapping:RKObjectMappingOperation.m:291 Did not find mappable attribute value keyPath 'time'
2011-10-12 12:36:48.145 MyProject[5119:207] T restkit.object_mapping:RKObjectMappingOperation.m:291 Did not find mappable attribute value keyPath 'someValue'
2011-10-12 12:36:48.145 MyProject[5119:207] T restkit.object_mapping:RKObjectMappingOperation.m:291 Did not find mappable attribute value keyPath 'lastChange'
2011-10-12 12:36:48.145 MyProject[5119:207] T restkit.object_mapping:RKObjectMappingOperation.m:291 Did not find mappable attribute value keyPath 'uuid'
2011-10-12 12:36:48.145 MyProject[5119:207] D restkit.object_mapping:RKObjectMappingOperation.m:448 Mapping operation did not find any mappable content
2011-10-12 12:36:48.146 MyProject[5119:207] T restkit.network:RKRequest.m:211 Prepared POST URLRequest '<NSMutableURLRequest http://someurl/api/sync?request=provide_key>'. HTTP Headers: {
Accept = "application/json";
"Content-Length" = 0;
}. HTTP Body: .
  • ¿utiliza CoreData en su proyecto?
  • Yo lo hago, pero en caso de que iban a sugerir, no me siento necesito RestKit del CoreData de integración en este caso. La pregunta se sitúa actualmente como está 😉
InformationsquelleAutor Ivan Vučica | 2011-10-11

2 Comentarios

  1. 18

    La restkit no fondo enrutable camino para NSArray, porque define la hoja de ruta para NSManagedObject clase. Usted probablemente desea crear una clase personalizada, dicen MySyncEntity que tiene el ivars de definir en su asignación. A continuación, crear su asignación como este:

    RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[MySyncEntity class]];
    ....
    [myManager setSerializationMIMEType:RKMIMETypeJSON];
    [[myManager router] routeClass:[MySyncEntity class] toResourcePath:@"/sync"];

    entonces usted debería ser capaz de publicar su objeto a la API de backend como un objeto JSON.

    Aclaración:

    En este caso, queremos publicar una matriz de NSManagedObject instancias en una basada en JSON API. Para ello necesitamos crear una sincronización de la entidad, que mantiene los objetos en una matriz:

    @interface MySyncEntity : NSObject {}
    @property (nonatomic, retain) NSArray* mySyncArray;
    ...
    @end 

    La mySyncArray tendrá la capacidad de carga, nos gustaría presentar al resto de backend. A continuación, vamos a crear el mapeo adecuado para ambos NSManagedObject que será enviado en mySyncArray y la MySyncEntity propia entidad.

    RKObjectManager *manager = [RKObjectManager objectManagerWithBaseURL:kBaseUrl];
    ...
    RKObjectMapping *mngObjMapping = [RKObjectMapping mappingForClass:[NSManagedObject class]]; 
    [mngObjMapping mapKeyPath: @"time" toAttribute:@"time"];  
    [mngObjMapping mapKeyPath: @"recordLevel" toAttribute:@"recordLevel"];
    .... //map as many properties as you wish
    [[manager mappingProvider] setSerializationMapping:[mngObjMapping inverseMapping]
    forClass:[NSManagedObject class]];
    //now, we create mapping for the MySyncEntity
    RKObjectMapping *syncEntityMapping = [RKObjectMapping mappingForClass:[MySyncEntity class]];
    [syncEntityMapping mapKeyPath:@"mySyncArray" toRelationship:@"mySyncArray" withMapping:mngObjMapping];
    [[manager mappingProvider] setSerializationMapping:[syncEntityMapping inverseMapping]
    forClass:[MySyncEntity class]];

    Ahora con las asignaciones definidas y podemos publicar el objeto en el servidor

    [manager postObject:mySyncInstance delegate:nil];

    El contenido de mySyncInstance matriz será asignada de acuerdo a mngObjMapping y enviado a definido extremo rest.

    • Así que, me explícitamente la necesidad de «contener» la NSArray como un yo-var de un nuevo objeto con el fin de presentar la matriz para el servidor? No puedo, después de haber definido la asignación para NSMutableObjects que se encuentran en la matriz, sólo tiene que enviar la matriz directamente?
    • no estoy seguro de que va a trabajar – siempre he anidado básico tipos de datos de debajo de mi ‘envolver’ clase porque me traslado de otros datos (no de una matriz simple). De cualquier manera, se mezclan un montón de diferentes clases en su asignación, se define una asignación para NSMutableDictionary donde el diccionario no tiene ningún ivars como uuid y tal, establece que la asignación de & definir la ruta de NSManagedObject y, sin embargo, publicar una instancia de NSArray. Usted tiene que atenerse a la misma clase, a través de su definición
    • Yo supuse que NSMutableDictionary es la «asignación inversa», es decir, si yo fuera la descarga de los datos (que actualmente estoy no haciendo), me gustaría obtener como diccionarios. A través de KVC, todo debería funcionar™. Ya estoy enviando NSManagedObjects, me acaba de definir la asignación para ellos. Por último, tengo que pagarle un NSArray – y esto es lo que en realidad no funciona.
    • se intenta el enfoque que he indicado en mi respuesta? La idea de la asignación inversa es que usted puede descargar la misma entidad que usted necesita para empujar de nuevo en la API de REST. Así, se definen sólo una asignación (de la API para la entidad) y, a continuación, «automágicamente» crear nueva serialización de asignación basado en el original (descargar) la cartografía.
    • Como era de esperar, esto no hace nada para ayudar a: RestKit todavía no sabe cómo hacer el mapa de la __NSArrayI clase. Detalles: he implementado una nueva clase SyncBlob que tiene una sola propiedad readonly array. He definido una asignación para SyncBlob y su propiedad.
    • ¿cuál es la restkit registro de salida para su SyncBlob intento?
    • permítanos continuar esta discusión en el chat
    • gracias por resolver el problema en el chat! me fui a través de todo el asunto y finalmente obtuvo lo que necesitaba. excelente.
    • Veo que dar delegado:nil al post. Lo que si quiero asignar el resultado a los objetos administrados? He intentado eso, y me da este error. No se puede asignar una colección de objetos en un no-mutable de la colección.
    • He abierto un nuevo hilo aquí. stackoverflow.com/q/11373448/772481
    • Esta solución también trabajó para mí. Tuve que hacer algunos ajustes del servidor de así, porque el JSON que se envía no es una lista de enties, sino más bien como un objeto mySyncArray con una serie de entidades incrustado en él.
    • Las respuestas anteriores no son relevantes para Restkit 0.2. github.com/RestKit/RestKit/wiki/…

  2. 3

    Como una aclaración, me gustaría señalar que en mja la respuesta la clave es

    [syncEntityMapping mapKeyPath:@"mySyncArray" toRelationship:@"mySyncArray" withMapping:mngObjMapping];

    Este dice «el mySyncArray ruta de acceso clave es una matriz que contiene los objetos que deben ser asignadas de acuerdo a mngObjMapping«.

Dejar respuesta

Please enter your comment!
Please enter your name here