Hi I'm trying to post NSManagedObject to the server using Rest Kit. Could somebody take a look and tell me what I'm doing wrong ?
This is my json structure for post request which I tested by using RubyMine REST client and it posted object properly:
{
"name":"test name",
"mobile":"22334455",
"dob":"1989-12-12",
"medications":"test",
"medical_conditions":"",
"watch":
{
"phonewatchno":"123789",
"latitude":-33.99,
"longitude":151.11,
"gmaps":null,
"battery_life":null,
"last_update_time":null,
"location":"",
"short_imei":null,
"rssi":null,
"charging_status":null,
"voltage":null,
"network":null,
"altitude":null,
"ip_addr":null,
"button_press_time":null,
"last_keep_alive":null
}
}
My post method looks like the following one :
id params = #{#"name": #"Tinder",
#"mobile":#"20934920",
#"dob":#"1989-12-12",
#"medications":#"pills",
#"medical_conditions":#"lkas",
#"watch":
#{
#"phonewatchno":#"239847239",
#"latitude":#"-33.99",
#"longitude":#"151.11",
#"gmaps":#"",
#"battery_life":#"",
#"last_update_time":#"",
#"location":#"",
#"short_imei":#"",
#"rssi":#"",
#"charging_status":#"",
#"voltage":#"",
#"network":#"",
#"altitude":#"",
#"ip_addr":#"",
#"button_press_time":#"",
#"last_keep_alive":#""
}
};
RKResponseDescriptor *responseDescr= [RKResponseDescriptor responseDescriptorWithMapping:[MappingProvider myMapping] method:RKRequestMethodPOST pathPattern:#"/myPath.json" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager]addResponseDescriptor:responseDescr];
[[RKObjectManager sharedManager]setRequestSerializationMIMEType:RKMIMETypeJSON];
[[[RKObjectManager sharedManager]HTTPClient]postPath:#"/myPath.json" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Mapped object %#",responseObject);
[self dismissViewControllerAnimated:YES completion:nil];
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"An error occuered: %#",error);
}];
}
Thanks in advance
EDIT 1:
NSEntityDescription *watchEntityDesc = [NSEntityDescription entityForName:#"Watches" inManagedObjectContext:[[RKObjectManager sharedManager]managedObjectStore].mainQueueManagedObjectContext];
Watches *watch = [[Watches alloc]initWithEntity:watchEntityDesc insertIntoManagedObjectContext:[[RKObjectManager sharedManager]managedObjectStore].mainQueueManagedObjectContext];
watch.phonewatchno = [NSNumber numberWithInt:124512];
watch.latitude = [NSNumber numberWithDouble:-33.99];
watch.longitude = [NSNumber numberWithDouble:151.11];
watch.location = #"test location";
watch.gmaps = [NSNumber numberWithInt:12];
watch.battery_life = [NSNumber numberWithInt:78];
watch.last_update_time = [NSDate date];
watch.last_keep_alive = [NSDate date];
watch.short_imei = [NSNumber numberWithInt:1233];
watch.rssi = [NSNumber numberWithInt:2];
watch.charging_status = [NSNumber numberWithInt:1];
watch.voltage = [NSNumber numberWithInt:200];
watch.network = #"WIFI";
watch.altitude = [NSNumber numberWithInt:1];
watch.ip_addr = #"196.12.12.04";
watch.button_press_time = [NSNumber numberWithInt:4];
NSEntityDescription *wearersEntityDesc = [NSEntityDescription entityForName:#"Wearers" inManagedObjectContext:[[RKObjectManager sharedManager]managedObjectStore].mainQueueManagedObjectContext];
Wearers *wearer = [[Wearers alloc]initWithEntity:wearersEntityDesc insertIntoManagedObjectContext:[[RKObjectManager sharedManager]managedObjectStore].mainQueueManagedObjectContext];
wearer.name =#"test";
wearer.mobile = #"109283190";
wearer.medical_conditions = #"test";
wearer.medications = #"test";
wearer.dob = [NSDate date];
wearer.watches = [NSSet setWithObject:watch];
RKEntityMapping *watchesMapping = [RKEntityMapping mappingForEntityForName:#"Watches" inManagedObjectStore:[[EdisseDateModel sharedDataModel]objectStore]];
[watchesMapping addAttributeMappingsFromDictionary:#{
#"id": #"watch_id",
#"altitude":#"altitude",
#"battery_life":#"battery_life",
#"button_press_time":#"button_press_time",
#"charging_status":#"charging_status",
#"gmaps":#"gmaps",
#"ip_addr":#"ip_addr",
#"last_keep_alive":#"last_keep_alive",
#"last_update_time":#"last_update_time",
#"latitude":#"latitude",
#"longitude":#"longitude",
#"location":#"location",
#"network":#"network",
#"phonewatchno":#"phonewatchno",
#"rssi":#"rssi",
#"short_imei":#"short_imei",
#"updated_at":#"updated_at",
#"voltage":#"voltage",
#"wearer_id":#"wearer_id",
#"updated_at":#"updated_at",
}
];
[watchesMapping addConnectionForRelationship:#"wearer" connectedBy:#{
#"wearer_id":#"wearer_id"
}];
[watchesMapping setIdentificationAttributes:#[#"watch_id"]];
RKResponseDescriptor *responseDescr = [RKResponseDescriptor responseDescriptorWithMapping:watchesMapping method:RKRequestMethodPOST pathPattern:#"/watches.json" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager]addResponseDescriptor:responseDescr];
RKEntityMapping *wearersMapping = [RKEntityMapping mappingForEntityForName:#"Wearers" inManagedObjectStore:[[EdisseDateModel sharedDataModel] objectStore]];
[wearersMapping addAttributeMappingsFromDictionary:#{
#"id":#"wearer_id",
#"at_risk": #"at_risk",
#"created_at": #"created_at",
#"dob": #"dob",
#"geo_radius": #"geo_radius",
#"medical_conditions":#"medical_conditions",
#"medications":#"medications",
#"mobile":#"mobile",
#"name":#"name",
#"status":#"status",
#"updated_at":#"updated_at",
#"wearer_photo_content_type":#"wearer_photo_content_type",
#"wearer_photo_file_size":#"wearer_photo_file_size",
#"wearer_photo_file_name":#"wearer_photo_file_name",
}
];
wearersMapping.identificationAttributes = #[#"wearer_id"];
[wearersMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"watch" toKeyPath:#"watches" withMapping:watchesMapping]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:wearersMapping method:RKRequestMethodPOST pathPattern:#"/wearers.json" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[wearersMapping inverseMapping] objectClass:[Wearers class] rootKeyPath:nil method:RKRequestMethodPOST ];
[[RKObjectManager sharedManager]addResponseDescriptor:responseDescriptor];
[[RKObjectManager sharedManager]addRequestDescriptor:requestDescriptor];
[[RKObjectManager sharedManager]setRequestSerializationMIMEType:RKMIMETypeJSON];
[[RKObjectManager sharedManager]setAcceptHeaderWithMIMEType:#"application/json"];
[[RKObjectManager sharedManager]postObject:wearer path:#"/wearers.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
NSLog(#"Response : %#",mappingResult.array);
}
failure:^(RKObjectRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#",error.userInfo.description);
}];
Now I'm getting error from failure block in my Xcode console like below :
Error: {
AFNetworkingOperationFailingURLRequestErrorKey = "<NSMutableURLRequest: 0x178210760> { URL: https://www.test.com/wearers.json }";
AFNetworkingOperationFailingURLResponseErrorKey = "<NSHTTPURLResponse: 0x170421be0> { URL: https://www.test.com/wearers.json } { status code: 500, headers {\n Connection = \"keep-alive\";\n \"Content-Length\" = 48;\n \"Content-Type\" = \"application/json; charset=utf-8\";\n Date = \"Fri, 06 Jun 2014 03:43:59 GMT\";\n Server = \"nginx/1.6.0 + Phusion Passenger 4.0.42\";\n Status = \"500 Internal Server Error\";\n \"X-Powered-By\" = \"Phusion Passenger 4.0.42\";\n \"X-Request-Id\" = \"6ce273e7-4130-47c3-91de-8020db49426a\";\n \"X-Runtime\" = \"0.011948\";\n} }";
NSErrorFailingURLKey = "https://www.test.com/wearers.json";
NSLocalizedDescription = "Expected status code in (200-299), got 500";
NSLocalizedRecoverySuggestion = "{\"status\":\"500\",\"error\":\"Internal Server Error\"}";
You need to create a request descriptor against NSDictionary and then not use the HTTPClient to action the post, just use the object manager (because the client knows nothing about request or response descriptors).
Following your edit your server is throwing an error - check the server log. Your code now looks ok for sending wearers with nested watches and receiving watches and connecting them by foreign key mapping. You need to check exactly what is sent with Charles against what the server is expecting.
Related
I have the following mapping:
RKEntityMapping *dashboardTeam = [RKEntityMapping mappingForEntityForName:#"DashboardTeam" inManagedObjectStore:managedObjectStore];
[dashboardTeam setAssignsDefaultValueForMissingAttributes:NO];
[dashboardTeam setAssignsNilForMissingRelationships:YES];
[dashboardTeam setShouldMapRelationshipsIfObjectIsUnmodified:YES];
[dashboardTeam addAttributeMappingsFromArray:#[#"id", #"name"]];
RKEntityMapping *dashboardLeague = [RKEntityMapping mappingForEntityForName:#"DashboardLeague" inManagedObjectStore:managedObjectStore];
[dashboardLeague setAssignsDefaultValueForMissingAttributes:YES];
[dashboardLeague setAssignsNilForMissingRelationships:YES];
[dashboardLeague setShouldMapRelationshipsIfObjectIsUnmodified:YES];
[dashboardLeague addAttributeMappingsFromArray:#[#"id", #"name"]];
[dashboardTeam addRelationshipMappingWithSourceKeyPath:#"league" mapping:dashboardLeague];
RKEntityMapping *dashboardGame = [RKEntityMapping mappingForEntityForName:#"DashboardGame" inManagedObjectStore:managedObjectStore];
[dashboardGame addAttributeMappingsFromArray:#[#"id", #"name", #"away", #"home", #"startTime"]];
[dashboardGame setAssignsNilForMissingRelationships:YES];
[dashboardGame setAssignsDefaultValueForMissingAttributes:YES];
[dashboardGame setShouldMapRelationshipsIfObjectIsUnmodified:YES];
RKDynamicMapping *dynamicGameMapping = [RKDynamicMapping new];
[dynamicGameMapping setObjectMappingForRepresentationBlock:^RKObjectMapping *(id representation) {
RKObjectMapping *testListMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
for (NSString *key in representation) {
[testListMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:key toKeyPath:key withMapping:dashboardGame]];
}
[testListMapping setAssignsNilForMissingRelationships:YES];
[testListMapping setAssignsDefaultValueForMissingAttributes:YES];
return testListMapping;
}];
[dashboardGame addRelationshipMappingWithSourceKeyPath:#"league" mapping:dashboardLeague];
RKResponseDescriptor *teams = [RKResponseDescriptor responseDescriptorWithMapping:dashboardTeam method:RKRequestMethodGET pathPattern:#"/api/3/dashboard" keyPath:#"teams" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKResponseDescriptor *games = [RKResponseDescriptor responseDescriptorWithMapping:dynamicGameMapping method:RKRequestMethodGET pathPattern:#"/api/3/dashboard" keyPath:#"games" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager] addResponseDescriptorsFromArray:#[teams, games]];
And the following fetch request:
[self.rkObjectManager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:DashData.pathPattern];
NSDictionary *argsDict = nil;
BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict];
if (match)
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"DashboardGame"
inManagedObjectContext:[RKObjectManager sharedManager].managedObjectStore.persistentStoreManagedObjectContext];
[fetchRequest setEntity:entity];
return fetchRequest;
}
return nil;
}];
My issue is that after I get the initial server response, say with 1 league that has 10 games - if I delete a game and re-fetch the league from the server the orphaned object doesn't get deleted from Core Data. Using my fetch request results in all games being deleted.
In my Core Data model I have the delete rule set to Nullify and have tried all others but I'm not sure how to solve this, in the past I have used simple fetch requests like above but it doesn't seem to work when it's within a relationship.
What am I missing here?
Edit: I was able to get the objects to map using an answer here
Now I just need to get the orphaned objects to delete but the fetch request isn't working
I am reviving an old project that originally used RestKit 0.10, and now am using RestKit 0.24. The old version still works, but unfortunately RestKit 0.10 is not 64-bit compatible and hence does not submit to the AppStore (and it is certainly time to update anyway).
I cannot get an object to post correctly. In RestKit 0.10, properties without values were not sent to the server, whereas it seems in RestKit 0.20 they are. I have tried explicitly setting assignsDefaultValueForMissingAttributes to NO, but it doesn't seem to make a difference.
The server expects the following format:
{"response": {"assessment_id":"1","time_taken":"60"},
"answer": [
{"question_number": 1, "answer_value": 3},
{"question_number": 2, "answer_value": 2},
{"question_number": 3, "answer_value": 1},
]
}
I have set up an object CompletedAssessment which contains a Response object and an array of Answer objects. (Note that when these objects are received from the server, many more properties need to be received than need to be sent).
#interface CompletedAssessment : NSObject {
Response *response;
NSArray *answers;
}
#interface Answer : NSObject {
NSNumber *identifier;
NSNumber *responseId;
NSNumber *questionNumber;
NSString *answerHistory;
NSString *answerValue;
NSString *answerText;
NSNumber *timeTaken;
}
#interface Response : NSObject {
NSNumber *identifier;
NSNumber *assessmentId;
NSNumber *timeTaken;
NSNumber *clientId;
NSString *assessmentShortName;
NSString *score;
NSString *interpretation;
NSString *dateCreated;
NSString *localTime;
}
I set the mapping up as follows:
RKObjectMapping *answerMapping = [RKObjectMapping mappingForClass:[Answer class]];
answerMapping.assignsDefaultValueForMissingAttributes = NO;
[answerMapping addAttributeMappingsFromDictionary:#{
#"id": #"identifier",
#"response_id": #"responseId",
#"question_number": #"questionNumber",
#"answer_history": #"answerHistory",
#"answer_value": #"answerValue",
#"answer_text": #"answerText",
#"time_taken": #"timeTaken"
}];
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[Response class]];
responseMapping.assignsDefaultValueForMissingAttributes = NO;
[responseMapping addAttributeMappingsFromDictionary:#{
#"id": #"identifier",
#"client_id": #"clientId",
#"assessment_id": #"assessmentId",
#"time_taken": #"timeTaken",
#"score": #"score",
#"assessment_short_name": #"assessmentShortName",
#"interpretation": #"interpretation",
#"created": #"dateCreated",
#"local_time": #"localTime"
}];
RKObjectMapping *completedAssessmentMapping = [RKObjectMapping mappingForClass:[CompletedAssessment class]];
completedAssessmentMapping.assignsDefaultValueForMissingAttributes = NO;
[completedAssessmentMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"response" toKeyPath:#"response" withMapping:responseMapping]];
[completedAssessmentMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"answer" toKeyPath:#"answers" withMapping:answerMapping]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:completedAssessmentMapping method:RKRequestMethodGET pathPattern:nil keyPath:#"data.completedAssessment" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager] addResponseDescriptor:responseDescriptor];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[completedAssessmentMapping inverseMapping] objectClass:[CompletedAssessment class] rootKeyPath:nil method:RKRequestMethodPOST];
[[RKObjectManager sharedManager] addRequestDescriptor:requestDescriptor];
[objectManager.router.routeSet addRoute:[RKRoute
routeWithClass:[CompletedAssessment class]
pathPattern:#"clients/:response.clientId/responses"
method:RKRequestMethodPOST]] ;
Logging reveals the end JSON appears in this format:
{"response":
{"interpretation":null,"id":null,"score":null,"client_id":15,"local_time":"2015-8-6 13:8:34","time_taken":5,"assessment_short_name":null,"assessment_id":8,"created":null},
"answer":[
{"answer_value":"0","id":null,"answer_text":null,"answer_history":null,"time_taken":null,"response_id":null,"question_number":1},
{"answer_value":"1","id":null,"answer_text":null,"answer_history":null,"time_taken":null,"response_id":null,"question_number":2}
]}
And RestKit logging confirms the null mapping:
restkit.object_mapping:RKMappingOperation.m:873 Mapped relationship object from keyPath 'response' to 'response'. Value: {
"assessment_id" = 8;
"assessment_short_name" = "<null>";
"client_id" = 15;
created = "<null>";
id = "<null>";
interpretation = "<null>";
"local_time" = "2015-8-6 13:8:34";
score = "<null>";
"time_taken" = 5;
}
restkit.object_mapping:RKMappingOperation.m:715 Mapped attribute value from keyPath 'identifier' to 'id'. Value: (null)
...
Please help!
You are creating a new mapping calling [selfCompletedAssessmentMapping inverseMapping] in this line:
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[selfCompletedAssessmentMapping inverseMapping] objectClass:[CompletedAssessment class] rootKeyPath:nil method:RKRequestMethodPOST];
Save it to a variable and assign assignsDefaultValueForMissingAttributes to NO before creating the descriptor:
RKObjectMapping *requestMapping = [selfCompletedAssessmentMapping inverseMapping];
requestMapping.assignsDefaultValueForMissingAttributes = NO;
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[CompletedAssessment class] rootKeyPath:nil method:RKRequestMethodPOST];
The problem is that I need to remove the attribute #"unitprice" entirely from the payload when the value is nil, but keep it in there if it has a value in the request. So the payload for OrderLine would look as follows accordingly: #{"id":#"orderlineId", #"unitprice":#"unitprice"} OR #{"id":#"orderlineId"} Please note that the mapping is a one-to-many relationship. Is it possible to do this? Your help is really appreciated thank you!
/*
requestDescriptor
*/
+(RKObjectMapping*) getSalesOrderMapping:(RKRequestMethod)method {
RKEntityMapping *requestMapping = [RKEntityMapping mappingForEntityForName:#"SalesOrder"
inManagedObjectStore:[RKManagedObjectStore defaultStore]];
RKEntityMapping *orderLinesMapping = [RKEntityMapping mappingForEntityForName:#"OrderLine"
inManagedObjectStore:[RKManagedObjectStore defaultStore]];
requestMapping.identificationAttributes = #[ #"salesOrderId" ];
NSMutableDictionary *attributeMappings = [NSMutableDictionary dictionaryWithDictionary:#{
#"id": #"salesOrderId",
}];
NSDictionary *orderLineAttributeMappings = #{
#"id": #"orderlineId",
#"unitprice": #"unitPrice"
};
[orderLinesMapping addAttributeMappingsFromDictionary:orderLineAttributeMappings];
[requestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"lines"
toKeyPath:#"salesOrderToOrderLines"
withMapping:orderLinesMapping]];
return requestMapping;
}
Set assignsDefaultValueForMissingAttributes to NO on the mapping. You shouldn't need 2 different mappings (unless you do want to include nil in the JSON for some attributes).
It seems impossible to implement dynamic request descriptor with 1-to-many relationship. So I had to build NSMutableDictionary manually by checking against nil value and then add the properties with its values like the following
[objectManager postObject:nil
path:#"/salesorder"
parameters:[self customSalesOrderRequestMapping]
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {... }
- (NSMutableDictionary *) customSalesOrderRequestMapping {
customSalesOrderAttributeDictionary = [NSMutableDictionary new];
if (selectedSalesOrder.salesOrderId) [customSalesOrderAttributeDictionary addEntriesFromDictionary:#{#"id": selectedSalesOrder.salesOrderId}];
if (selectedSalesOrder.salesOrderToOrderLines.count > 0) {
NSMutableArray *orderLinesMutableArray = [NSMutableArray new];
for (OrderLine *orderLine in selectedSalesOrder.salesOrderToOrderLines)
{
NSMutableDictionary *orderLineMutableDictionary = [NSMutableDictionary new];
if (orderLine.orderlineId) [orderLineMutableDictionary addEntriesFromDictionary:#{#"id": orderLine.orderlineId}];
if (orderLine.unitPrice) [orderLineMutableDictionary addEntriesFromDictionary:#{#"unitprice": orderLine.unitPrice}];
[orderLinesMutableArray addObject:orderLineMutableDictionary];
}
[customSalesOrderAttributeDictionary addEntriesFromDictionary:#{#"lines": orderLinesMutableArray}];
}
return customSalesOrderAttributeDictionary;
}
Below is the JSON response that I get back:
{
"notificationId": 121,
"activities": [
143,
149]
}
Below is the mapping:
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping addAttributeMappingsFromDictionary:#{#"notificationId" : #"notificationId",
#"activities": #"activities"}];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:#""
statusCodes:statusCodeSet];
[self.objectManager postObject:invitation path:#"/notifications" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSString *notificationId1 = [mappingResult.dictionary valueForKey:#"notificationId"];
NSArray *activitesArray1 = [mappingResult.dictionary valueForKey:#"activities"];
NSString *notificationId2 = [mappingResult.dictionary objectForKey:#"notificationId"];
NSArray *activitesArray2 = [mappingResult.dictionary objectForKey:#"activities"];
NSLog(#"notificaiton ID %#", notificationId1);
NSLog(#"Activites %#", activitesArray1);
NSLog(#"notification ID %#", notificationId2);
NSLog(#"Activites %#", activitesArray2);
NSLog(#"Activites Array %#", activitesArray);
NSLog(#"mappingResult Dictionary %#", mappingResult.dictionary);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"Failusre");
}];
}
Log:
2014-04-21 19:17:51.273 App[57446:4403] I restkit.network:RKObjectRequestOperation.m:250 POST 'http://www.domain.com/notifications' (200 OK / 1 objects) [request=0.2371s mapping=0.0035s total=0.2446s]
2014-04-21 19:17:51.274 App[57446:60b] notification ID (null)
2014-04-21 19:17:51.274 App[57446:60b] Activites (null)
2014-04-21 19:17:51.274 App[57446:60b] notification ID (null)
2014-04-21 19:17:51.274 App[57446:60b] Activites (null)
2014-04-21 19:17:51.274 App[57446:60b] Activites Array (
)
2014-04-21 19:17:51.275 App[57446:60b] mappingResult Dictionary {
"" = {
activities = (
143,
149
);
notificationId = 121;
};
}
Why are all the values Null? How can I get the values of notificationId back as an NSString and activitiesin an array ? Can this be done without creating a mapping class?
Because your response descriptor is wrong. It should be:
[RKResponseDescriptor responseDescriptorWithMapping:mapping
method:RKRequestMethodPOST
pathPattern:#"/notifications"
keyPath:nil
statusCodes:statusCodeSet];
so that it matches the request you're sending (a POST, not a GET is the main issue).
For some unknow reason, it looks like, there is a wrapper object in the dictionary, that has key value #"" so first extract that and then everything else. Activities itself do look like array, so simply:
NSArray *activities = [[mappingResult.dictionary objectForKey:#""] objectForKey:#"activities"];
However that notification looks tricky, because it probably is a number. So if it is a consistent type, use:
NSNumber *notificationID = [[mappingResult.dictionary objectForKey:#""] objectForKey:#"notificationId"];
NSSring *notificationIDString = [notificationID stringValue];
So, i m sending a POST request for the first time. I m Mapping classes and as I thought and read from the Documentation that it would work in this way:
Init RK:
- (void)initRK{
if(!manager){
manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:BASE_CONTEXT_URL]];
}
if (!reqMapping) {
reqMapping = [RKObjectMapping requestMapping];
}
}
POST Method:
// Configure a request mapping for our Article class. We want to send back title, body, and publicationDate
RKObjectMapping* deviceRequestMapping = [RKObjectMapping mappingForClass:[DeviceDTO class]];
[deviceRequestMapping addAttributeMappingsFromArray:#[ #"model", #"name", #"systemName", #"systemVersion", #"devToken" ]];
RKObjectMapping* msRequestMapping = [RKObjectMapping mappingForClass:[MemberShipDTO class]];
[msRequestMapping addAttributeMappingsFromArray:#[ #"validSince", #"validTill" ]];
RKObjectMapping* countryRequestMapping = [RKObjectMapping mappingForClass:[CountryDTO class]];
[countryRequestMapping addAttributeMappingsFromArray:#[ #"idNumberDTO", #"iso2DTO", #"short_nameDTO", #"calling_codeDTO" ]];
RKObjectMapping* userRequestMapping = [RKObjectMapping requestMapping];
[userRequestMapping addAttributeMappingsFromArray:#[ #"displayName", #"phoneNumber", #"status", #"userID" ]];
[userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil toKeyPath:#"device" withMapping:deviceRequestMapping]];
[userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil toKeyPath:#"memberShip" withMapping:msRequestMapping]];
[userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil toKeyPath:#"country" withMapping:countryRequestMapping]];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:userRequestMapping objectClass:[User class] rootKeyPath:#"user"];
//Create Objects
UserDTO *user = [[UserDTO alloc]init];
user.displayName = userDTO.displayName;
user.phoneNumber = userDTO.phoneNumber;
user.status = userDTO.status;
user.userID = userDTO.userID;
user.country = userDTO.country;
DeviceDTO *device = [[DeviceDTO alloc]init];
device.name = devDTO.name;
device.systemName = devDTO.systemName;
device.systemVersion = devDTO.systemVersion;
device.model = devDTO.model;
device.devToken = [[NSUserDefaults standardUserDefaults]objectForKey:PUSHTOKEN_USER_DEFAULTS_KEY];
user.deviceInfo = device;
MemberShipDTO *ms = [[MemberShipDTO alloc]init];
ms.validSince = [NSDate date];
ms.validTill = [[UtilitieHandler new] getDateByAdd:+1 :0 :0 :0];
user.memberShipDetails = ms;
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"application/json"];
[[RKObjectManager sharedManager] setRequestSerializationMIMEType:RKMIMETypeJSON];
[[RKObjectManager sharedManager] setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[[RKObjectManager sharedManager] addRequestDescriptor:requestDescriptor];
[[RKObjectManager sharedManager] postObject:user path:#"user/integrate" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult){
RKLogInfo(#"Load collection of Articles: %#", mappingResult.array);
}failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(#"Operation failed with error: %#", error);
}];
So I tried different things and after i used wireshark to capture the request it returns that theres no content send. That means the mapping is not working correct. I tried a lot and nothing helped. Any advice would be great!
Here the captured packet:
POST /WAZZUUPWS/rest/service/user/integrate HTTP/1.1
Host: 192.168.2.115:8080
Accept-Encoding: gzip, deflate
Accept: application/json
Content-Length: 0
Connection: keep-alive
Accept-Language: de;q=1, en;q=0.9, fr;q=0.8, ja;q=0.7, nl;q=0.6, it;q=0.5
User-Agent: WAZZUUP!/1.0 (iPhone; iOS 6.1.4; Scale/2.00)
It might just be a typo in your question but requestDescriptor doesn't appear to be linked to the UserDTO class.
It seems like you do not have an understanding of Core Data objects yet. Objects that are persisted using Core Data are subclasses of NSManagedObject and have to be created differently. Read further on this link:
http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/CoreData/Articles/cdCreateMOs.html
As for the current problem, you have to use this instead:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"UserDTO" inManagedObjectContext:[RKManagedObjectStore defaultStore].mainQueueManagedObjectContext];
UserDTO *user = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
However, if UserDTO is a subclass of NSObject, that would need to change to NSManagedObject.
My workflow is something like this - create Core Data model and use mogenerator to automatically generate the NSManagedObject class definitions. Read more about it here:http://raptureinvenice.com/getting-started-with-mogenerator/