ioscocoacore-datarestkitrestkit-0.20

RestKit validation failing when updating CoreData object with nested data (Cocoa error 1550)


I'm writing a unit test to check if my CoreData objects are getting updated properly. The problem is that when I try to update a Project that has no Address, with data that has an Address, I get a validation error. Everything works as expected when the Project already has an Address, I have marked the code that adds an address and passes the test

The structure of my model is as follows:

[Project]
    -localId [int]
    -serverId [int]
    -name [string]
    -address [Address]

[Address]
    -lineOne [string]
    -lineTwo [string]
    -city [string]
    -state [string]
    -country [string]
    -zip [string]
    -project [Project]

Project and Address have a one-to-one relationship in CoreData and all of the attributes and relationships are marked as optional. I am using serverId and lineOne as identification within RestKit.

This is the unit test in question:

// Create an object to match our criteria
Project *project = [NSEntityDescription insertNewObjectForEntityForName:@"Project" inManagedObjectContext:[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext];
[project setValue:@(1) forKey:@"serverId"];

//----IF I ADD THESE TWO LINES THE TEST PASSES----
//Address *address = [NSEntityDescription insertNewObjectForEntityForName:@"Address" inManagedObjectContext:[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext];
//[project setValue:address forKey:@"address"];



NSDictionary* fakeJson = @{@"id" : @1, @"name" : @"TEST", @"address" : @{@"line_1":@"123 Apple Street",@"line_2":@"Apartment 4",@"city":@"New York",@"country":@"USA",@"state":@"New York",@"zip":@"12345"}};

RKMappingTest* idTest = [RKMappingTest testForMapping:[Project showResponseMapping] sourceObject:fakeJson destinationObject:nil];
[idTest setManagedObjectContext:[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext];
[idTest performMapping];

//Assert that the destinationObject for the mapping is the existing one
XCTAssertEqualObjects(project, idTest.destinationObject, @"Expected to match the project, but did not");

And this is the error being thrown:

2014-09-03 16:14:28.599 TestProject[3692:607] E restkit.object_mapping:RKMappingOperation.m:342 Validation failed while mapping attribute at key path 'address' to value <Address: 0x115b57a0> (entity: Address; id: 0x115b1e20 <x-coredata:///Address/t5016F936-C646-4CD0-84EC-366D2A8C7F056> ; data: {
city = "New York";
country = USA;
lineOne = "123 Apple Street";
lineTwo = "Apartment 4";
localId = nil;
project = nil;
state = "New York";
zip = 12345;
}). Error: The operation couldn’t be completed. (Cocoa error 1550.)
2014-09-03 16:14:28.600 Closeout[3692:607] E restkit:RKLog.m:151 Validation Error
                    NSLocalizedDescriptionKey:      The operation couldn’t be completed. (Cocoa error 1550.)
                    NSValidationKeyErrorKey:            address
                    NSValidationPredicateErrorKey:  (null)
                    NSValidationObjectErrorKey:
<Project: 0x115a4e50> (entity: Project; id: 0x115aa980 <x-coredata:///Project/t5016F936-C646-4CD0-84EC-366D2A8C7F055> ; data: {
address = nil;
localId = nil;
name = TEST;
serverId = 1;
})

Since the test passes if I add a blank address to the initial CoreData object, the issue isn't with the mappings or the Address data being invalid. I can also tell from the log that the new Address object is being created properly, it is just failing to link them via the relationship.

Thanks for any help.


Solution

  • Solved this after two full days of head scratching. The problem was the code in the AppDelegate generated by Xcode when you check the "Use CoreData" box on a new project. It was creating a CoreData stack and then we were creating our own stack for unit tests and when RestKit was pulling data down it was trying to connect objects from different contexts (Even though we specified one context in every operation we did). Removing all of the CoreData generated code in the AppDelegate fixed the issue.