Mam jednostkę (na Core Data
) nazywa Contact
, każdy kontakt ma Neighborhood
, User
i ContactOrigin
podmioty z nim powiązane. Kiedy pobieram dane JSON z serwera, otrzymuję coś takiego:
{
"contact" : [
{
"prospect" : {
"pkProspect" : 21,
"name" : "Test Contact",
"email" : "test@domain.com",
"phone" : "5555555555",
"address" : "Test Avenue",
"media" : {
"pkMedia" : 3,
"name" : "Referência Entrevista You Move"
},
"neighborhood" : {
"pkNeighborhood" : 15857,
"name" : "Donwtown"
}
},
"user" : {
"firstName" : "John",
"pkPerson" : 5,
"lastName" : "Doe"
}
}
]
}
Jak więc widzisz, mam szereg kontaktówa każdy kontakt ma węzeł użytkownika, węzeł sąsiedzki i węzeł multimedialny (którego używam jako źródła w mojej bazie danych). Wygląda na to, że RestKit mapuje to we właściwy sposób za pomocą tego kodu:
// Getting the object manager.
RKObjectManager *objectManager = [RKObjectManager sharedManager];
// Relationship mappings.
RKManagedObjectMapping *neighborhoodMapping = [RKManagedObjectMapping mappingForClass:[Neighborhood class] inManagedObjectStore:objectManager.objectStore];
neighborhoodMapping.primaryKeyAttribute = @"identifier";
[neighborhoodMapping mapKeyPath:@"pkNeighborhood" toAttribute:@"identifier"];
RKManagedObjectMapping *originMapping = [RKManagedObjectMapping mappingForClass:[ContactOrigin class] inManagedObjectStore:objectManager.objectStore];
originMapping.primaryKeyAttribute = @"identifier";
[originMapping mapKeyPath:@"pkMedia" toAttribute:@"identifier"];
RKManagedObjectMapping *userMapping = [RKManagedObjectMapping mappingForClass:[User class] inManagedObjectStore:objectManager.objectStore];
userMapping.primaryKeyAttribute = @"identifier";
[userMapping mapKeyPath:@"pkPerson" toAttribute:@"identifier"];
// Creating the contact mapping for the request.
RKManagedObjectMapping *contactMapping = [RKManagedObjectMapping mappingForClass:[Contact class] inManagedObjectStore:objectManager.objectStore];
contactMapping.primaryKeyAttribute = kContactFieldNameId;
[contactMapping mapKeyPath:@"prospect.neighborhood" toRelationship:@"addressNeighborhood" withMapping:neighborhoodMapping];
[contactMapping mapKeyPath:@"prospect.media" toRelationship:@"origin" withMapping:originMapping];
[contactMapping mapKeyPath:@"user" toRelationship:@"user" withMapping:userMapping];
[contactMapping connectRelationship:@"addressNeighborhood" withObjectForPrimaryKeyAttribute:@"identifier"];
[contactMapping connectRelationship:@"origin" withObjectForPrimaryKeyAttribute:@"identifier"];
[contactMapping connectRelationship:@"user" withObjectForPrimaryKeyAttribute:@"identifier"];
[contactMapping mapKeyPath:@"prospect.pkProspect" toAttribute:@"identifier"];
[contactMapping mapKeyPath:@"prospect.name" toAttribute:@"name"];
[contactMapping mapKeyPath:@"prospect.email" toAttribute:@"email"];
[contactMapping mapKeyPath:@"prospect.phone" toAttribute:@"phone"];
[contactMapping mapKeyPath:@"prospect.address" toAttribute:@"address"];
// Setting the result mapping.
[objectManager.mappingProvider setObjectMapping:contactMapping forKeyPath:@"contact"];
// Loading data.
[objectManager loadObjectsAtResourcePath:resourcePath usingBlock:^(RKObjectLoader *loader) {
loader.delegate = self;
loader.userData = delegate;
}];
Po zakończeniu mapowania otrzymuję następujący komunikat (pokazuję tylko plik User
błąd):
2012-07-06 18:20:23.016 Contact Manager[8254:10c03] E restkit.core_data:RKManagedObjectStore.m:250 Core Data Save Error
NSLocalizedDescription: The operation couldn’t be completed. (Cocoa error 1570.)
NSValidationErrorKey: user
NSValidationErrorPredicate: (null)
NSValidationErrorObject:
<Contact: 0x917dff0> (entity: Contact; id: 0x917e070 <x-coredata:///Contact/t9D9EE4AE-142A-45EC-88C1-E97833729D0C2> ; data: {
address = "Test Avenue";
addressNeighborhood = "0x918b5b0 <x-coredata://6E5AB6F3-AFF4-460E-A37D-285A105178F0/Neighborhood/p21>";
email = "test@domain.com";
identifier = 21;
name = "Test Contact";
origin = nil;
phone = 5555555555;
user = nil;
})
2012-07-06 18:20:23.024 Contact Manager[8254:10c03] E restkit.core_data:RKManagedObjectLoader.m:167 Failed to save managed object context after mapping completed: The operation couldn’t be completed. (Cocoa error 1560.)
Jak widać, oba origin
i user
mają wartość null i powoduje to błąd, gdy próbuję je zapisać Core Data
ponieważ te pola są wymagane, ale jeśli spojrzymy na logi z RestKit, zobaczymy, że te obiekty zostały poprawnie przeanalizowane i faktycznie istnieją w bazie danych.
2012-07-06 18:20:22.938 Contact Manager[8254:10c03] D restkit.object_mapping:RKObjectMappingOperation.m:636 Starting mapping operation...
2012-07-06 18:20:22.940 Contact Manager[8254:10c03] T restkit.object_mapping:RKObjectMappingOperation.m:637 Performing mapping operation: RKObjectMappingOperation for "User" object. Mapping values from object {
firstName = John;
lastName = Doe;
pkPerson = 5;
} to object <User: 0x5ca9d60> (entity: User; id: 0xc5aa7a0 <x-coredata://6E5AB6F3-AFF4-460E-A37D-285A105178F0/User/p1> ; data: {
contacts = "<relationship fault: 0xc5ab580 "contacts">";
email = "john@domain.com";
identifier = 5;
ip = "0.0.0.0";
isLoggedIn = 1;
language = "en";
name = "John Doe";
password = 4badaee57fed5610012a296273158f5f;
}) with object mapping <RKManagedObjectMapping:0x5ca78b0 objectClass=User keyPath mappings => (
"RKObjectKeyPathMapping: pkPerson => identifier"
)>
2012-07-06 18:20:22.942 Contact Manager[8254:10c03] T restkit.object_mapping:RKObjectMappingOperation.m:330 Mapping attribute value keyPath "pkPerson" to "identifier"
2012-07-06 18:20:22.943 Contact Manager[8254:10c03] D restkit.object_mapping:RKObjectPropertyInspector.m:107 Cached property names and types for Class "User": {
accessibilityHint = NSString;
accessibilityLabel = NSString;
accessibilityLanguage = NSString;
accessibilityValue = NSString;
contacts = NSSet;
email = NSString;
identifier = NSNumber;
ip = NSString;
isLoggedIn = NSNumber;
language = NSString;
name = NSString;
password = NSString;
}
2012-07-06 18:20:22.944 Contact Manager[8254:10c03] T restkit.object_mapping:RKObjectMappingOperation.m:347 Skipped mapping of attribute value from keyPath "pkPerson to keyPath "identifier" -- value is unchanged (5)
2012-07-06 18:20:22.946 Contact Manager[8254:10c03] D restkit.object_mapping:RKObjectMappingOperation.m:643 Finished mapping operation successfully...
2012-07-06 18:20:22.966 Contact Manager[8254:10c03] T restkit.object_mapping:RKObjectMappingOperation.m:597 Mapped relationship object from keyPath "user" to "user". Value: <User: 0x5ca9d60> (entity: User; id: 0xc5aa7a0 <x-coredata://6E5AB6F3-AFF4-460E-A37D-285A105178F0/User/p1> ; data: {
contacts = "<relationship fault: 0xc5ab580 "contacts">";
email = "john@domain.com";
identifier = 5;
ip = "0.0.0.0";
isLoggedIn = 1;
language = "pt_BR";
name = "John Doe";
password = 4badaee57fed5610012a296273158f5f;
})
2012-07-06 18:20:22.968 Contact Manager[8254:10c03] D restkit.object_mapping:RKObjectMappingOperation.m:643 Finished mapping operation successfully...
Więc moje pytanie brzmi: dlaczego user
i origin
mają wartość null, jeśli analizator składni znalazł te obiekty w bazie danych? Czy jest coś nie tak z mapowaniem?
Odpowiedzi:
1 dla odpowiedzi № 1Po wielu debugowaniu znalazłem sposób, aby to naprawić. Po pierwsze, fakt, że używałem tego samego klucza podstawowego (@"identifier"
) dla każdego obiektu zepsuło mapowanie.
Po tym usunąłem plik [contactMapping connectRelationship:withObjectForPrimaryKeyAttribute:]
ponieważ nie jest to potrzebne, a teraz wszystko wydaje się działać.