Reputation: 874
I am currently developing an iOS Messenger application and I would like to talk about these two classes relationship: MessengerConversation
and MessengerMessage
.
Supposing that I already have a local MessengerConversation instance which can have many MessengerMessage instances related into its messages
relationship property, I would like to request and mapping the following JSON payload:
Request: GET /conversations/:conversationID/msgs
Response:
{
"messages": [
{
...
"messageid": n,
"content": "..."
...
},
...
]
}
As the response JSON payload didn't indicate which conversation the delivered messages are from. I used the following approach to fix this issue into my MessengerManager
class (Responsible for interacting with the shared RKObjectManager instance):
- (void)objectLoader:(RKObjectLoader *)objectLoader willMapData:(inout id *)mappableData {
//
// GETs Resource Paths.
if ([objectLoader method] == RKRequestMethodGET) {
if ([pathMatcherConversationsMessagesGET matchesPath:objectLoader.resourcePath tokenizeQueryStrings:NO parsedArguments:Nil]) {
//
// Get requested conversationID from the following resource path Pattern:
// kMessengerManagerResourcePathMessages: /conversations/:conversationID/msgs
NSNumber *currentConversationID = Nil;
NSDictionary *arguments = Nil;
BOOL isMatchingPattern = [pathMatcherConversationsMessagesGET matchesPattern:kMessengerManagerResourcePathConversationsMessagesGET
tokenizeQueryStrings:YES
parsedArguments:&arguments];
if (isMatchingPattern) {
currentConversationID = [arguments objectForKey:@"conversationID"];
//
// Get the original returned array of messages:
NSArray *origMessagesArray = [*mappableData valueForKeyPath:@"messages"];
NSMutableArray *reformattedData = [NSMutableArray arrayWithCapacity:[origMessagesArray count]];
//
// Create copies of objects adding the already knew reference.
for (NSDictionary *origMessagesArrayObject in origMessagesArray) {
NSMutableDictionary *newMessagesArrayObject = [origMessagesArrayObject mutableCopy];
[newMessagesArrayObject setObject:currentConversationID forKey:@"conversationid"];
[reformattedData addObject:newMessagesArrayObject];
}
//
// Replace the new objects instead of the response objects
[*mappableData setObject:reformattedData forKey:@"messages"];
}
}
}
}
And so everything worked properly. That is, all loaded MessengerMessages from the specified MessengerConversation (into the RKObjectLoader resource path) are being inserted into the wanted relationship.
Now comes the real problem, as I am working with my MessengerManager class which adopts the RKObjectLoaderProtocol, I could implement the objectLoader:willMapData:
method. But as my View classes are using the RKFetchedResultsTableController
and every table controller instance is also its RKObjectLoader delegate, I don't know which would be the best practice to enable a RKFetchedResultsTableController instance to update a received JSON payload before the mapping operation.
Shall I subclass it?
And are there better ways to map received objects into a pre-defined object specified by a RKObjectLoader resource path (e.g: GET /conversations/2/msg where all resulted messages should be mapped inside the defined MessengerConversation object with its primary key value equal to 2)?
Best regards,
Piva
Upvotes: 1
Views: 645
Reputation: 10633
You don't need this method. When you launch the RKObjectLoader, set your Conversation object as the targetObject and make the mapping relative to this object. For example:
RKManagedObjectMapping* cMapping = [RKManagedObjectMapping mappingForClass: [MessengerConversation class]];
RKManagedObjectMapping* mMapping = [RKManagedObjectMapping mappingForClass: [MessengerMessage class]];
//Configure mappings
[cMapping mapKeyPath: @"messages" toRelationship: @"messages" withObjectMapping: mMapping];
[mappingProvider setMapping cMapping forKeyPath: @""];
Upvotes: 4