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!
Related
When I POST a mapped model through Restkit the resultant Json looks like so, the doubles are strings, I want them to be doubles:
{
Coordinate = (
"39.2",
"-121.0"
);
}
I want:
{
Coordinate = (
39.2,
-121.0
);
}
this is my mapping
+(RKObjectMapping *)mapping
{
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[self class]];
[mapping addAttributeMappingsFromArray:#[#"Coordinate"]];
return mapping;
}
When setting the coordinate of the Location object:
#interface MYLocationDTO : NSObject
#property (strong, nonatomic) NSArray *Coordinate;
+(RKObjectMapping *)mapping;
#end
I am passing in an array of two nsnumbers, that were set from double values.
Anyone know of how to post this nsarray collection as numbers not strings?
Thanks!
Here is my post call:
-(void)updateLocationOfUserWithLocationDTO:(WHMLocationDTO *)dto withCompletionBlock:(void (^)(BOOL, NSString *))callbackBlock
{
//whim-ios.herokuapp.com/users/password-reset
RKObjectManager *manager = [WHMDataController getManagerWithSession];
RKObjectMapping *requestMapping = [[WHMLocationDTO mapping] inverseMapping];
RKRequestDescriptor *requestDesc = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[WHMLocationDTO class] rootKeyPath:nil method:RKRequestMethodPOST];
[manager addRequestDescriptor:requestDesc];
RKObjectMapping *responseMapping = [WHMResponseMapping responseMapping];
RKDynamicMapping *dynamicMapping = [WHMResponseMapping createDynamicMappingWithResponseMapping:responseMapping];
[manager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:dynamicMapping method:RKRequestMethodPOST pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
//POST
__weak __typeof__(self) weakSelf = self;
[manager postObject:dto
path:#"user/loc"
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *result)
{
Why not use Apple's API to generate the JSON, as demonstrated in this article: http://www.raywenderlich.com/5492/working-with-json-in-ios-5
and just POST the JSON?
I am developing iPhone application and using Restkit for consuming services and put data on server. I am working with Restkit first time. I want to put data on server then I implemented the restkit put method, and it executed successfully and getting response "SUCCESS" but when I retrieving data then it doesn't affecting data means not getting last put data on server. So can anybody tell me what is wrong with this?? I used the following code I used :
////Response Mapping values
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[NSMutableArray class]];
[responseMapping addAttributeMappingsFromArray:#[#"SenderId", #"SentDate", #"Status",#"GroupId", #"Message"]];
//Request Mapping values
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping]; // objectClass == NSMutableDictionary
[requestMapping addAttributeMappingsFromArray:#[#"SenderId", #"SentDate", #"Status",#"GroupId", #"Message"]];
ITRestKitServices *restkitService = [[ITRestKitServices alloc] initWithDelegate:self];
[restkitService putDataONserverBulletin:bulletinMutableArray pathPattern:#"bulletin" keyPath:#"" userName:appDelegate.user.Email password:appDelegate.user.SessionToken requestMapping:requestMapping responseMapping:responseMapping];
// And following code to put data on server in service I used:
// initialize AFNetworking HTTPClient
NSURL *baseURL = [NSURL URLWithString:BASE_URL_STRING];
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
[client setAuthorizationHeaderWithUsername:userName password:password];
//set pathPattern
NSString *path = [NSString stringWithFormat:#"%#/%#",BASE_PATH_STRING,pathPattern];
//StatusCodes
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
//Request Descriptor
RKRequestDescriptor *requestDescriptor =
[RKRequestDescriptor requestDescriptorWithMapping:requestMapping
objectClass:[Bulletin class]
rootKeyPath:nil
method:RKRequestMethodPUT];
//Response Descriptor
RKResponseDescriptor *userResponseDescriptor =
[RKResponseDescriptor responseDescriptorWithMapping:responseMapping
method:RKRequestMethodPUT
pathPattern:path
keyPath:keyPath
statusCodes:statusCodes];
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
[objectManager addRequestDescriptor:requestDescriptor];
[objectManager addResponseDescriptor:userResponseDescriptor];
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
if(appDelegate.isLoading == NO)
{
[appDelegate startLoading];
}
[objectManager putObject:dataObject
path:path
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
NSLog(#"Bulletin Success");
}
failure:^(RKObjectRequestOperation *operation, NSError *error)
{
if(appDelegate.isLoading == YES)
{
[appDelegate stopLoading];
}
NSLog(#">>> Error: %#", error);
}];
I'm trying to post new managed object with image to the web database as below and everything works fine for me except the little weird bug. When the managed object is uploaded successfully, 2 rows are added instead of one to the UITableView. When I'm refreshing the UITableView the one of the previously added UITableViewCell is populating with uploaded image. When I rebuild the app everything works fine. Previously added managed object is displayed correctly without duplication. Does anyone can take a look at my code and tell me what is the reason for that bug and how can I fix it? Let me know if you need more code.
-(void)postRequest{
NSEntityDescription *watchEntityDesc = [NSEntityDescription entityForName:#"Watches" inManagedObjectContext:[[RKObjectManager sharedManager]managedObjectStore].mainQueueManagedObjectContext];
Watches *watch = [[Watches alloc]initWithEntity:watchEntityDesc insertIntoManagedObjectContext:[[RKObjectManager sharedManager]managedObjectStore].mainQueueManagedObjectContext];
watch.phonewatchno = #"124512";
watch.latitude = [NSNumber numberWithDouble:-33.856870];
watch.longitude = [NSNumber numberWithDouble:151.215279];
NSEntityDescription *wearersEntityDesc = [NSEntityDescription entityForName:#"Wearers" inManagedObjectContext:[[RKObjectManager sharedManager]managedObjectStore].mainQueueManagedObjectContext];
Wearers *wearer = [[Wearers alloc]initWithEntity:wearersEntityDesc insertIntoManagedObjectContext:[[RKObjectManager sharedManager]managedObjectStore].mainQueueManagedObjectContext];
wearer.name =_nameTextField.text,
wearer.watches =[NSSet setWithObject:watch];
RKEntityMapping *watchesMapping = [RKEntityMapping mappingForEntityForName:#"Watches" inManagedObjectStore:[[EFDateModel sharedDataModel]objectStore]];
[watchesMapping addAttributeMappingsFromDictionary:#{
#"id": #"watch_id",
#"latitude":#"latitude",
#"longitude":#"longitude",
#"phonewatchno":#"phonewatchno",
}
];
[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:[[EFDateModel sharedDataModel] objectStore]];
[wearersMapping addAttributeMappingsFromDictionary:#{
#"id":#"wearer_id",
#"name":#"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"];
UIImage *image =[UIImage imageWithCGImage:_wearerImage.CGImage scale:0.4 orientation:UIImageOrientationUp];
NSMutableURLRequest *request = [[RKObjectManager sharedManager] multipartFormRequestWithObject:wearer method:RKRequestMethodPOST path:#"/wearers.json" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:UIImagePNGRepresentation(image)
name:#"wearer_photo"
fileName:#"photo.png"
mimeType:#"image/png"];
}];
NSManagedObjectContext *moc =[[[RKObjectManager sharedManager]managedObjectStore]mainQueueManagedObjectContext];
RKManagedObjectRequestOperation *managedObjectOperation = [[RKObjectManager sharedManager]managedObjectRequestOperationWithRequest:request managedObjectContext:moc success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"Mapping result = %#",mappingResult.array);
[[RKObjectManager sharedManager]removeResponseDescriptor:responseDescriptor];
[[RKObjectManager sharedManager]removeRequestDescriptor:requestDescriptor];
[[NSNotificationCenter defaultCenter]
postNotificationName:#"ReloadTable"
object:self];
[self dismissViewControllerAnimated:YES completion:nil];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"Error : \n %#",error.description);
}];
[[RKObjectManager sharedManager] enqueueObjectRequestOperation:managedObjectOperation];
}
Cheers
Every time you are calling this method you are calling alloc]initWithEntity:... insertIntoManagedObjectContext: twice and creating two new entity instances. You should probably be passing an entity instance to this method that it uses and not creating any new instances.
Also, it is inefficient to keep creating new descriptors and adding and removing them. And if you try to make 2 requests at the same time you will get an error. Configure the object manager once before you first use it and then just use it repeatedly without reconfiguring.
I'm doing a very basic POST request.
setting my requestSerializationMIMEType into RKMIMETypeFormURLEncoded as my server would expect (although it's the default).
Now in the log the request.body would look like this:
request.body=[param1]=test&[param2]=2724
Resulting unknown form values in the server.
The problem here is the param names, they're between square brackets, which I don't have an explanation why they're serialised like this!
My code is somehow exactly the same of the example provided on github.
NOTE: I have done the POST request manually without the square brackets and it's working fine.
EDIT
The code
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[GenericResponse class]];
[responseMapping addAttributeMappingsFromDictionary:#{#"error":#"error", #"status":#"status"}];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *genericDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:#"" keyPath:#"" statusCodes:statusCodes];
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
[requestMapping addAttributeMappingsFromDictionary:[User generateJSONMapping]];//dictionary mapping
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[User class] rootKeyPath:#"" method:RKRequestMethodPOST];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"https://foo.com/rest/createUser/"]];
[manager addRequestDescriptor:requestDescriptor];
[manager addResponseDescriptor:genericDescriptor];
manager.requestSerializationMIMEType=RKMIMETypeFormURLEncoded;
// POST to create
[manager postObject:user path:#"" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
NSLog(#"success");// the request is success but the params are not delivered to the server
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"fail");
}];
The User is very simple I guess
#interface User : NSObject
#property NSNumber *idShort;
#property NSNumber *idLong;
#property NSNumber *idCom;
#property NSString *comment;
#property NSString *token;
+ (NSDictionary *) generateJSONMapping;
#end
#implementation User
+ (NSDictionary *) generateJSONMapping
{
return #{
#"idShort": #"idShort",
#"idLong": #"idLong",
#"idCom":#"idCom",
#"comment":#"comment",
#"token":#"token",
};
}
#end
The problem is in the RKRequestDescriptor, passing rootKeyPath as an empty string would cause this.
Passing nil would solve the problem.
RKRequestDescriptor *requestDescriptor = [
RKRequestDescriptor requestDescriptorWithMapping:requestMapping
objectClass:[User class]
rootKeyPath:nil
method:RKRequestMethodPOST];
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.