Mapowanie relacji w RestKit za pomocą tablicy identyfikatorów nie działa

Próbuję odwzorować użytkowników i grupy na obiekty CoreData poprzez RestKit, zachowując relacje między nimi.

JSON dla użytkowników to coś w rodzaju

{"users":
  [{"fullname": "John Doe", "_id": "1"}
   ...
  ]
}

a JSON dla grup to coś w stylu

{"groups":
  [{"name": "John's group", "_id": "a",
    "members": ["1", "2"]
   ...
  ]
}

Mam też odpowiednie obiekty Core Data,User iGroup, z mapowaniem relacji jeden do wielu między grupami i użytkownikami. Właściwość relacji wGroup jest nazywanymembers i oddzielneNSArray nazywamemberIDs przechowuje tablicę identyfikatorów ciągów wszystkich użytkowników.

To, co chcę osiągnąć w RestKit, to załadować te obiekty i zmapować relację dla mnie. Kod ładowania użytkowników jest zwykłym standardem, a kod do ładowania grup jest podobny

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) {}];

Po uruchomieniu tego kodu kilka razy otrzymuję następujący komunikat ostrzegawczy (wydaje się być około dwa razy na relację):

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;
})

Dziwną rzeczą jest to, że relacja jest poprawnie skonfigurowana (nawet spojrzała na bazę danych sqlite i wszystko tam wygląda dobrze), ale nie jestem zadowolony z czegoś, co w kodzie RestKit wyraźnie się nie udaje i wydaje się mieć coś wspólnego z fałszywe mapowanie użytkownika, które tworzę w powyższym kodzie (jest puste, ponieważ nie ma nic do mapowania w tablicy ID).

Próbowałem alternatyw, na przykład dodając mapowanie ścieżki klucza:

[userMapping mapKeyPath:@"" toAttribute:@"identifier"];

Narzeka, oczywiście, ponieważ ścieżka klucza jest pusta

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 .

A jeśli spróbuję użyć prawdziwegoUser mapowanie

[groupMapping hasMany:@"members" withMapping:[[RKObjectManager sharedManager].mappingProvider objectMappingForKeyPath:@"users"]];

Dostaję następujący błąd

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.'

Wygląda na to, że RestKit próbuje odwzorować same ciągi ID w tablicy memberIDs naUser obiekty, które nie mają sensu. Widziałem przykłady, w których tablica relacji jest listą słowników z kluczami (np. Nazywanąid) z identyfikatorem odniesienia do innego obiektu, na przykład:

{"groups":
  [{"name": "John's group", "_id": "a",
    "members": [
      {"_id": "1"},
      {"_id": "2"}
     ]
   ...
  ]
}

Ale nie chcę zmieniać mojego JSON w ten sposób (poza tym mam nadzieję, że RestKit jest wystarczająco elastyczny, aby obsługiwać w inny sposób).

Czy ktoś wie, jaki jest właściwy sposób wykonywania tego rodzaju mapowania relacji w RestKit?

Aktualizacja

Skończyłem modyfikując interfejs REST, aby wysłać listę słowników zawierających identyfikatory obiektów użytkownika (tak jak w poprzednim przykładzie powyżej), i sprawił, że to zadziałało. Nadal nie do końca zadowolony z ustawień, ale kod wygląda teraz tak

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) {}];

Na wszelki wypadek pomaga to komuś innemu w podobnej sytuacji. Nadal mogą pojawić się problemy z podejściem, które podjąłem, ale jak na razie tak dobre (nawet obsługuje ładowanie poza kolejnością, co jest miłe) - nadal chciałbym usłyszeć od każdego, czy istnieje odpowiedź na moje pierwotne pytanie.

questionAnswers(1)

yourAnswerToTheQuestion