Das Zuordnen von Beziehungen in RestKit über ein Array von IDs funktioniert nicht
Ich versuche, Benutzer und Gruppen über RestKit CoreData-Objekten zuzuordnen, wobei die Beziehung zwischen beiden beibehalten wird.
Der JSON für die Benutzer ist so etwas wie
{"users":
[{"fullname": "John Doe", "_id": "1"}
...
]
}
und der JSON für die Gruppen ist so etwas wie
{"groups":
[{"name": "John's group", "_id": "a",
"members": ["1", "2"]
...
]
}
Ich habe auch entsprechende Core Data-Objekte,User
undGroup
, mit einer Eins-zu-Viele-Beziehung zwischen Gruppen und Benutzern. Die Beziehungseigenschaft inGroup
wird genanntmembers
und eine separateNSArray
namensmemberIDs
Enthält das Array der Zeichenfolgen-IDs aller Mitgliedsbenutzer.
Was ich in RestKit erreichen möchte, ist, diese Objekte zu laden und die Beziehung für mich abzubilden. Der Code zum Laden der Benutzer ist ein einfacher Standard, und der Code zum Laden der Gruppen ist ungefähr so
RKObjectManager* objectManager = [RKObjectManager sharedManager];
RKManagedObjectMapping* groupMapping = [RKManagedObjectMapping mappingForClass:[Group class] inManagedObjectStore:objectManager.objectStore];
groupMapping.primaryKeyAttribute = @"identifier";
[groupMapping mapKeyPath:@"_id" toAttribute:@"identifier"];
[groupMapping mapKeyPath:@"name" toAttribute:@"name"];
[groupMapping mapKeyPath:@"members" toAttribute:@"memberIDs"];
[objectManager.mappingProvider setMapping:groupMapping forKeyPath:@"groups"];
// Create an empty user mapping to handle the relationship mapping
RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class] inManagedObjectStore:objectManager.objectStore];
[groupMapping hasMany:@"members" withMapping:userMapping];
[groupMapping connectRelationship:@"members" withObjectForPrimaryKeyAttribute:@"memberIDs"];
RKObjectRouter* router = objectManager.router;
[router routeClass:[Group class] toResourcePath:@"/rest/groups/:identifier"];
[router routeClass:[Group class] toResourcePath:@"/rest/groups/" forMethod:RKRequestMethodPOST];
// Assume url is properly defined to point to the right path...
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:url usingBlock:^(RKObjectLoader *loader) {}];
Wenn ich diesen Code ausführe, wird die folgende Warnung mehrmals ausgegeben (scheint ungefähr zweimal pro Beziehung zu sein):
2012-10-24 08:55:10.170 Test[35023:18503] W restkit.core_data.cache:RKEntityByAttributeCache.m:205 Unable to add object with nil value for attribute 'identifier': <User: 0x86f7fc0> (entity: User; id: 0x8652400 <x-coredata:///User/t01A9EDBD-A523-4806-AFC2-9B06873D764E531> ; data: {
fullname = nil;
identifier = nil;
})
Das Seltsame ist, dass die Beziehung richtig eingerichtet wird (sogar in der SQLite-Datenbank, und dort sieht alles gut aus), aber ich bin nicht glücklich darüber, dass im RestKit-Code eindeutig etwas schief geht, und es scheint etwas damit zu tun zu haben Die falsche Benutzerzuordnung, die ich im obigen Code erstellt habe (sie ist leer, da im Array der IDs nichts zuzuordnen ist).
Ich habe Alternativen ausprobiert, zum Beispiel beim Hinzufügen einer Schlüsselpfadzuordnung:
[userMapping mapKeyPath:@"" toAttribute:@"identifier"];
Es beklagt sich offensichtlich, weil der Schlüsselpfad leer ist
2012-10-24 09:24:11.735 Test[35399:14003] !! Uncaught exception !!
[<__NSCFString 0xa57f460> valueForUndefinedKey:]: this class is not key value coding-compliant for the key .
Und wenn ich versuche das echte zu nutzenUser
Kartierung
[groupMapping hasMany:@"members" withMapping:[[RKObjectManager sharedManager].mappingProvider objectMappingForKeyPath:@"users"]];
Ich erhalte den folgenden Fehler
2012-10-24 09:52:49.973 Test[35799:18403] !! Uncaught exception !!
[<__NSCFString 0xa56e9a0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key _id.
2012-10-24 09:52:49.973 Test[35799:18403] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0xa56e9a0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key _id.'
Anscheinend versucht RestKit, die ID-Zeichenfolgen selbst im memberIDs-Array zuzuordnenUser
Objekte, die keinen Sinn machen. Ich habe Beispiele gesehen, bei denen das Beziehungsarray eine Liste von Wörterbüchern mit Schlüsseln ist (z. B. genanntid
) mit der Referenz-ID zum anderen Objekt, zum Beispiel:
{"groups":
[{"name": "John's group", "_id": "a",
"members": [
{"_id": "1"},
{"_id": "2"}
]
...
]
}
Aber ich möchte meinen JSON nicht auf diese Weise ändern (außerdem hoffe ich, dass RestKit flexibel genug ist, um den anderen Weg zu unterstützen.)
Weiß jemand, wie diese Art der Beziehungszuordnung in RestKit richtig funktioniert?
Aktualisieren
Am Ende habe ich die REST-Schnittstelle dahingehend geändert, dass eine Liste von Wörterbüchern mit den Benutzerobjekt-IDs gesendet wurde (genau wie im letzten Beispiel oben), und das hat funktioniert. Immer noch nicht ganz zufrieden mit dem Setup, aber der Code sieht jetzt so aus
RKObjectManager* objectManager = [RKObjectManager sharedManager];
RKManagedObjectMapping* groupMapping = [RKManagedObjectMapping mappingForClass:[Group class] inManagedObjectStore:objectManager.objectStore];
groupMapping.primaryKeyAttribute = @"identifier";
[groupMapping mapKeyPath:@"_id" toAttribute:@"identifier"];
[groupMapping mapKeyPath:@"name" toAttribute:@"name"];
[groupMapping mapKeyPath:@"members._id" toAttribute:@"memberIDs"];
[objectManager.mappingProvider setMapping:groupMapping forKeyPath:@"groups"];
// Create an empty user mapping to handle the relationship mapping
RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class] inManagedObjectStore:objectManager.objectStore];
userMapping.primaryKeyAttribute = @"identifier";
[userMapping mapKeyPath:@"_id" toAttribute:@"identifier"];
[groupMapping hasMany:@"members" withMapping:userMapping];
[groupMapping connectRelationship:@"members" withObjectForPrimaryKeyAttribute:@"memberIDs"];
RKObjectRouter* router = objectManager.router;
[router routeClass:[Group class] toResourcePath:@"/rest/groups/:identifier"];
[router routeClass:[Group class] toResourcePath:@"/rest/groups/" forMethod:RKRequestMethodPOST];
// Assume url is properly defined to point to the right path...
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:url usingBlock:^(RKObjectLoader *loader) {}];
Nur für den Fall, dass dies jemand anderem in einer ähnlichen Situation hilft. Es könnte immer noch Probleme mit meiner Vorgehensweise geben, aber soweit so gut (es funktioniert sogar beim Laden außerhalb der Reihenfolge, was nett ist) - würde mich immer noch freuen, von jemandem zu hören, wenn es eine Antwort auf meine ursprüngliche Frage gibt.