RestKit Object Mapping Relationships without KVC

2019-01-14 09:23发布

问题:

After reading the Object Mapping-Guide on GitHub for RestKit my problem didn't disappear, so perhaps somebody can say if RestKit could deal with the following idea.

Entities with Relationships

 Company 
 - unitID 
 - companyID
 - name
 - contacts* (Company -->> Contact | 1:n)

 Contact
 - unitID
 - companyID
 - contactID
 - lastName
 - firstName
 - account* (Contact >--> Company | 1:1)

JSON (Company)

 [
   {
      "unitID":"003CABD8DEB5DC13C",
      "companyID":"BSP-002999",
      "name":"Testcompany"
   }
 ]

JSON (Contact)

 [
   {
      "unitID":"DAC2ACCC125795D00",
      "companyID":"BSP-002999",
      "contactID":"CLP-015468",
      "firstName":"Mister",
      "lastName":"Wayne"
   }
 ]

Due to limitations I'm not able to nest the belonging contacts into the companies (otherwise I wouldn't write this), so I want to do this use when the data is mapped on import.

Question

Is it possible to map each Contact to it's belonging Company (identified by the attribute companyID) on import with given methods by RestKit?

If not, I would like to know the best solution for it. Thanks!


Background

In my first build of this app I've mapped the objects to the given entities (without relationships) and fetched all belonging contacts to a company with the predicate companyID = %@. Due to the amount of data (4000+ Companies, 7000+ Contacts) fetching all belonging contacts takes about a second - so I came up with the idea to use relationsships (which works perfect with local dummy data).


Solution

With the help of the given answer below my current mapping looks like the following (RestKit v.10).

// Setting up Restkit with objectStore
...

// Init objectMapping for Class Company
companyMapping = [RKManagedObjectMapping mappingForClass:[Company class] inManagedObjectStore:objectStore];
[companyMapping mapKeyPath:@"unitID" toAttribute:@"unitID"];
[companyMapping mapKeyPath:@"companyID" toAttribute:@"companyID"];
[companyMapping mapKeyPath:@"name" toAttribute:@"name"];
companyMapping.setDefaultValueForMissingAttributes = NO;
companyMapping.primaryKeyAttribute = @"companyID";

// Init objectMapping for Class Contact
contactMapping = [RKManagedObjectMapping mappingForClass:[Contact class] inManagedObjectStore:objectStore];
[contactMapping mapKeyPath:@"unitID" toAttribute:@"unitID"];
[contactMapping mapKeyPath:@"companyID" toAttribute:@"companyID"];
[contactMapping mapKeyPath:@"contactID" toAttribute:@"contactID"];
[contactMapping mapKeyPath:@"lastName" toAttribute:@"lastName"];
[contactMapping mapKeyPath:@"firstName" toAttribute:@"firstName"];
contactMapping.setDefaultValueForMissingAttributes = NO;
contactMapping.primaryKeyAttribute = @"contactID";

// Init relationships
[contactMapping mapRelationship:@"company" withMapping:companyMapping];
[contactMapping connectRelationship:@"company" withObjectForPrimaryKeyAttribute:@"companyID"];

// Get objects from server
...

回答1:

Yes, RestKit can hydrate this relationship for you at mapping time. On your RKManagedObjectMapping for your Contact model, you will need to do the following:

  • Add a relationship mapping to the parent Company: [objectMapping mapRelationship:@"company" withMapping:companyMapping]
  • Map the companyID attribute onto your Contact model
  • Ensure that you have the primaryKeyAttribute configured on both classes
  • Instruct RestKit to hydrate the relationship: [objectMapping connectRelationship:@"company" withObjectForPrimaryKeyAttribute:@"companyID"];

After RestKit has completed mapping a payload, it will pass back through the collection and hydrate any relationships. The processing is deferred until after mapping in case the payload actually creates objects that you need to satisfy the connections.

On the development branch, there is an alternative workflow available to you. Earlier this week I added support for hydrating a has-many relationship using an array of ID's in the payload. This would let you send the list of Contacts that belong to a company down in the payload instead. It may be more efficient for your use case.

Additional details from my post to the RestKit mailing list: http://groups.google.com/group/restkit/msg/416951f86b2862d1