I am trying to create a RKResponseDescriptor to get people in a session.
I have a response descriptor for /sessions but I don't know how to create it to get the people in the sessions /sessions/20/people (/sessions/sessionID/people).
My session response descriptor is;
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:sessionsMapping
pathPattern:#"/sessions"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
The response descriptor for the people in the session is;
RKResponseDescriptor *clientInSessionResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:clientsInSessionMapping
pathPattern:#"/sessions/:sessionID/people"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
I keep getting the error, "Failed with error: No response descriptors match the response loaded."
I noticed in the documentation there is a lot of usage of the :id but can't seem to figure it out. Also, should I use a RKPathMatcher to build the path?
Any help would be greatly appreciated.
What I did was a parameter substitution when sending the request path. So in your case I would do the following:
NSString *idValue; // this is the sessionID value
NSString *path = [#"/sessions/:sessionID/people" stringByReplacingOccurrencesOfString:#":sessionID" withString:idValue];
[[RKObjectManager sharedManager] getObjectsAtPath:path parameters:nil success:^(RKObjectRequestOperation *operation,RKMappingResult *mappingResult)
{
// handle success
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(#"*** RK load FAIL");
}]
Related
I am having NSString parameters in my object getting set to NSNull when null is returned in the JSON. I would like the the NSString to be set to nil. Any Ideas?
I have tried setting [mapping setAssignsDefaultValueForMissingAttributes:NO]; but that does not seem to work even when I implement changes from Fix 1714. I'm really just spinning my wheels at this point.
Here is everything I have for making this call so far.
Returned JSON
{
val1 = "something";
val2 = "<null>";
}
Class cMyClass
#interface cMyClass : NSObject {
NSString *val1;
NSString *val2;
}
RKObjectMapping
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[cMyClass class]];
[mapping addAttributeMappingsFromDictionary:#{#"val1":#"val1", #"val2":#"val2"}];
RKResponseDescriptor
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:#"GetMyClass" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKObjectManager
NSURL *baseURL = [NSURL URLWithString:#"http://www.domain.com/MyAPI.svc/rest"];
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL];
[objectManager addResponseDescriptor:responseDescriptor];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager.HTTPClient setDefaultHeader:#"Accept" value:RKMIMETypeJSON];
[objectManager.HTTPClient setParameterEncoding:AFJSONParameterEncoding];
API Call
NSDictionary *params = ...
objectManager getObjectsAtPath:#"GetMyClass" parameters:params success:(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
completionBlock:(mappingResult.array[0]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
failureBlock(error);
}];
I'm grasping at straws since I am just starting out with Restkit myself...but, do you perhaps think there might be an issue with the mappings?
It looks like the values in your cMyClass are ivars instead of properties. If I am not mistaken, unless otherwise stated, those are "protected" so you can't really access those if you are calling an instance of the class. Maybe move them to properties and see if it works from there!
I'm trying to send a POST request to a server. I'm using RESTKit with a request descriptor:
RKObjectMapping *messageRequestMapping = [RKObjectMapping requestMapping ];
[messageRequestMapping addAttributeMappingsFromArray:#[#"to", #"msg"]];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:messageRequestMapping objectClass:[PostMessage class] rootKeyPath:nil method:RKRequestMethodAny];
[objectManager addRequestDescriptor:requestDescriptor];
and then I'm using postObject:path:parameters:success:failure:
PostMessage *postMessage = [PostMessage new];
postMessage.to = self.pickedPerson.name;
postMessage.msg = message.messgaeContent;
[[RKObjectManager sharedManager] postObject:postMessage path:#"/post" parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"SUCCES: message sent to server");
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"WARNING");
}];
The problem is that the failure block always gets called even though I see that the POST request got to the server successfully. When I test the same POST request with a simple REST client I get a status code of 200.
The error I get is:
Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "No response descriptors match the response loaded." UserInfo=0x10c67adf0 {NSLocalizedFailureReason=A 200 response was loaded from the URL 'http://bla.com/post', which failed to match all (0) response descriptors:, NSErrorFailingURLStringKey=http://bla.com/post, NSErrorFailingURLKey=http://bla.com/post, NSUnderlyingError=0x10c60add0 "No mappable object representations were found at the key paths searched.", keyPath=null, NSLocalizedDescription=No response descriptors match the response loaded.}
I'm not sure if I have to set a responseDescriptor or not.
Can't I just set the expected status code like I do when setting a responseDescriptor?
EDIT:
I've added a response descriptor:
// message response after a post
RKObjectMapping *messageResponseForPostMapping = [RKObjectMapping mappingForClass:[PostMessage class]];
[messageResponseForPostMapping addAttributeMappingsFromArray:#[#"success"]];
RKResponseDescriptor *messageResponseForPostDescriptor =
[RKResponseDescriptor responseDescriptorWithMapping:messageResponseForPostMapping
method:RKRequestMethodPOST
pathPattern:#"post"
keyPath:#""
statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptorsFromArray:#[messageResponseDescriptor, personResponseDescriptor, messageResponseForPostDescriptor]];
as the server's response is:
{
"success" : "Message sent successfully."
}
and it still fails with the same error.
The error message tells you that
"No mappable object representations were found at the key paths searched."
So, either you gave an incorrect response descriptor, or you did not define one.
Giving a correct response descriptor should fix the issue.
This is an example response descriptor:
RKObjectMapping* mapping = [RKObjectMapping mappingForClass:<YOURCLASSHERE>];
...
RKResponseDescriptor * responseDescriptor = [RKResponseDescriptor
responseDescriptorWithMapping:mapping
method:RKRequestMethodPOST
pathPattern:path keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
I didn't actually find what's wrong with my response descriptor.
My way of dealing with this was to change the response on the server. Instead of sending back a json file, the server now sends response code of 201, and RESTKit does not fail anymore.
I have been seeing quite a few posts of this nature where a trailing '/' (or lack of) causes the pattern matching to fail.
My problem, however, is that there is no pattern to match against.
My error looks like this:
"No response descriptors match the response loaded." UserInfo=0xcb8a660 {NSErrorFailingURLStringKey=http://domain.herokuapp.com/auth/identity/callback,
NSLocalizedFailureReason=A 200 response was loaded from the URL 'http://domain.herokuapp.com/auth/identity/callback',
which failed to match all (3) response descriptors:
http://domain.herokuapp.com pathPattern=(null)
statusCodes=200-299>
failed to match: response path '/auth/identity/callback' did not match the path pattern '(null)'.
"did not match the path pattern '(null)'" is what I assume is the problem.
Setting up the objectmanager and HttpClient:
+ (void) fireUpRestkit
{
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
//base URL #"http://domain.herokuapp.com"
NSURL *baseURL = [[SCURLManager sharedInstance] baseURL];
AFHTTPClient * client = [AFHTTPClient clientWithBaseURL:baseURL];
[client setDefaultHeader:#"Accept" value:RKMIMETypeJSON];
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
NSAssert(objectManager, #"objectManager did not instantiate correctly");
}
My request looks like this:
[[RKObjectManager sharedManager] postObject:user
path:/auth/identity/callback"
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
My descriptors are setup like this:
RKObjectManager *objectManager = [RKObjectManager sharedManager];
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[SCUserEntity class]];
[userMapping addAttributeMappingsFromDictionary:[SCUserEntity keyMapping]];
RKRequestDescriptor * requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:userMapping.inverseMapping
objectClass:[SCUserEntity class]
rootKeyPath:nil
method:RKRequestMethodPOST];
RKResponseDescriptor * responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager addRequestDescriptor:requestDescriptor];
I can't find the reason for the pattern I give when doing the postRequest does not seem to
be there when the request returns.
I have stepped through the buildResponseMappingsDictionary and subsequent matches~ methods. When the request is made they all return the correct descriptors, but when the request needs mapping it doesn't work.
I get a 200 OK from the server, I see both the request and response bodies and they seem correct.
Hope someone can help me spot the probably obvious missing part:)
It has nothing to do with the path pattern. It's the method.
You are using:
[[RKObjectManager sharedManager] postObject:user ...
but you have a response descriptor:
method:RKRequestMethodGET
i.e. one for POST and one for GET
I would like to know if there is a specific tutorial on how to do a POST request with RESTKit. I have looked at some tutorials but I haven't found any that say, "This is exactly how you do a POST request with RESTKit." Help is much appreciated.
Assuming you already have a mapped model, you can simply perform this:
First, set a requestDescriptor with the inverseMapping of your responseDescriptor, assuming you have one with your mapping.
//This is used for mapping responses, you already should have one of this. PS:[Data mapping] is a method that returns an RKObjectMapping for my model. You should create yours or use a previous created one
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[Data mapping] pathPattern:nil keyPath:#"data" statusCodes:statusCodeSet];
[[RKObjectManager sharedInstance] addResponseDescriptor:responseDescriptor];
//Inverse mapping, to perform a POST
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[[Data mapping] inverseMapping] objectClass:[Data class] rootKeyPath:nil];
[[RKObjectManager sharedInstance] addRequestDescriptor:requestDescriptor];
After that, to perform a POST, just simply call the method below. Restkit will get the instance that you are trying to post, serialize it and send to the path chosen.
[[RKObjectManager sharedInstance] postObject:instanceOfYourModel path:yourPathHere parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"Success");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"Error");
}];
If you don't have a mapped model, let me know so we can try something else.
i just update a content using restkit patchobject..when first time the method call invoked it leads success.but during second time call the same method ,the app crashes with NSInternal inconsistecy error.Cannot add adddescriptor for same class.thanks. below link also have same problem,but i dont know how to solve.
Restkit + Objective-c - Multiple calls to same web service
here is my method code
-(void)setContact:(int)_orgID :(int)_personID :(Person *)p1
{
AddressScreenViewController *addressView= [[AddressScreenViewController alloc]init];
addressView.mobileno = p1.mobile_phone;
addressView.workno = p1.work_phone;
addressView.homeno = p1.home_phone;
addressView.address1=p1.address1;
addressView.address2=p1.address2;
addressView.city=p1.city;
addressView.zip=p1.zip;
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
LoginAppDelegate * appDelegate = [[UIApplication sharedApplication] delegate];
RKObjectManager *objectManager = [RKObjectManager sharedManager];
[objectManager setRequestSerializationMIMEType:RKMIMETypeJSON];
RKObjectMapping *personRequestMapping = [RKObjectMapping requestMapping];
[personRequestMapping addAttributeMappingsFromDictionary:#{ #"mobileno" : #"phone_numbers.mobile_number", #"workno" : # "phone_numbers.work_number" , #"homeno" :#"phone_numbers.home_number",#"address1":#"mailing_address.address1",#"address2":#"mailing_address.address2",#"city":#"mailing_address.city",#"zip":#"mailing_address.zip"}];
RKLogConfigureByName("RestKit", RKLogLevelWarning);
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);
RKRequestDescriptor *requestDescriptor =[RKRequestDescriptor requestDescriptorWithMapping:personRequestMapping objectClass:[AddressScreenViewController class] rootKeyPath:#"person"];
[objectManager addRequestDescriptor:requestDescriptor];
NSString * orgPath = [NSString stringWithFormat:myurl];
[objectManager patchObject:addressView path:orgPath parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *result)
{
NSLog(#"result: %#", result);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"failuer function");
}];
}
The issue you are facing is because you are adding same request descriptor multiple times. You should set all request and response descriptor only once for example, in app delegate.
+ (void)setupDescriptors {
RKObjectManager *objectManager = [[AppDelegate appDelegate] objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
// Add Request Descriptors
//
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[Human rkEntityMappingForResponse:YES] method:RKRequestMethodAny pathPattern:nil keyPath:#"human" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKRequestDescriptor *userRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[User rkObjectMappingForRequest:YES] objectClass:[User class] rootKeyPath:#"user" method:RKRequestMethodAny];
RKRequestDescriptor *signupUserRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[User rkObjectMappingForSignupRequest:YES] objectClass:[User class] rootKeyPath:#"user" method:RKRequestMethodAny];
[objectManager addRequestDescriptorsFromArray:#[signupUserRequestDescriptor,userRequestDescriptor]];
RKResponseDescriptor *userResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[User rkEntityMappingForResponse:YES] method:RKRequestMethodAny pathPattern:nil keyPath:#"user" statusCodes:statusCodes];
[objectManager addResponseDescriptorsFromArray:#[userResponseDescriptor,responseDescriptor]];
}
But in some scenarios, you still want to add multiple request descriptor then this is done by dynamic mapping as answered by Author of REST Kit. Please see following link.
Adding two request descriptors for a given class in Restkit 0.2
I hope this helps.
You can't add a descriptor for the same key twice. You haven't added any code, but I know that you're adding all of your mappings and descriptors in the method where you're calling 'patch'. Don't...
Separate your configuration from your usage. Put all of your mapping and descriptor setup code into one method and call it once before you do anything else. Then, when you want to 'patch', call a different method which just does that and doesn't include any additional mappings.