How to Get Object based response in Restkit 0.20.3 - ios

Hi have used restkit in my several previous projects with version 0.10.0. But now i am going to move with new restkit v0.20.3.
I followed all the steps from upgrading 10.0 to 20.0 from HERE.
I am able execute my request and response also came under success blog. But i can get the property of my response object. That is very shocking for now. I can get value only by [data valueForKey:#""] which is not good i guess in restkit.
Can any one tell me about how we get value from object's property.
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"%lu", (unsigned long)mappingResult.array.count);
DataForResponse *data = [mappingResult.array objectAtIndex:0];
User *user = [data valueForKey:#"user"];
User *user = [[data.user allObjects] firstObject];
NSLog(#"%#",[user valueForKey:#"email"]);
RKLogInfo(#"Load collection of Users: %#", mappingResult.array);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"%#",operation.HTTPRequestOperation.responseString);
RKLogError(#"Operation failed with error: %#", error);
}];
My goal is to get value of email like from user.email

After searching & based on my restkit knowledge below code is worked.
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[DataForResponse objectMappingForDataResponse:LOGIN] method:RKRequestMethodPOST pathPattern:nil keyPath:#"data" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[rkomForLogin addResponseDescriptor:responseDescriptor];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[ responseDescriptor ]];
operation.targetObject = data;
[rkomForLogin postObject:nil path:#"login" parameters:dict success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
// Handled with articleDescriptor
NSLog(#"%#",operation.HTTPRequestOperation.responseString);
DataForResponse *data = [mappingResult.array objectAtIndex:0];
User *user = [[data.user allObjects] firstObject];
NSLog(#"%#",[user email]);
NSLog(#"%ld",operation.HTTPRequestOperation.response.statusCode);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
// Transport error or server error handled by errorDescriptor
NSLog(#"%#",operation.HTTPRequestOperation.responseString);
RKLogError(#"Operation failed with error: %#", error);
}];
This is same object based response that i was getting in restkit 0.10 so this is way to execute a request.

Related

Setting up iOS Restkit with Django Rest Framework

I have an API sitting at this url: https://evening-everglades-1560.herokuapp.com/api/v1/stocks/
I am trying to implement iOS RestKit with like so (this is in MasterViewController.m):
RKObjectMapping *stockMapping = [RKObjectMapping mappingForClass:[Stock class]];
[stockMapping addAttributeMappingsFromDictionary:#{#"stockId": #"id"}];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:stockMapping method:RKRequestMethodAny pathPattern:nil keyPath:#"" statusCodes:statusCodes];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"https://evening-everglades-1560.herokuapp.com/api/v1/stocks.json"]];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[responseDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
Stock *stock = [result firstObject];
NSLog(#"mapped w stock: %#", stock);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"failed w error: %#", [error localizedDescription]);
}];
[operation start];
This is what is logged:
2016-01-17 16:42:08.233 Stocks[9415:1208281] W restkit.object_mapping:RKMapperOperation.m:99 Adding mapping error: No mappable values found for any of the attributes or relationship mappings
2016-01-17 16:42:08.234 Stocks[9415:1208308] I restkit.network:RKObjectRequestOperation.m:250 GET 'https://evening-everglades-1560.herokuapp.com/api/v1/stocks.json' (200 OK / 0 objects) [request=0.4798s mapping=0.0042s total=0.5528s]
2016-01-17 16:42:08.235 Stocks[9415:1208245] mapped w stock: (null)`
I am not sure of what to put for the pathPattern and keyPath.
Thanks in advance!
It is fixed thanks to wain inquiring about "you haven't given your object definition." I forgot to define submitter in my stock.h cocoa class.
Adding #property(nonatomic, strong) NSString *submitter; to stock.h fixed it.

RestKit - POST array of objects with attachments

I am creating a task application which has offline mode.
While in offline mode, I am setting isSync attribute to false for each object, so that when network is available I could fetch these unsynced objects with predicate and POST them to server.
The problem is I am not being able to add attachments with each object.
In online I am sending POST request with attachment for single object like this:
if (attachments != nil && attachments.count > 0) {
task.total_attachments = [NSNumber numberWithInteger:attachments.count];
NSMutableURLRequest *request =[[RKObjectManager sharedManager] multipartFormRequestWithObject:task
method:RKRequestMethodPOST
path:URL_TASKS
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
int counter = 0;
for (NSDictionary *dic in attachments) {
[formData appendPartWithFileData:UIImageJPEGRepresentation([dic objectForKey:#"image"], 0.7)
name:[NSString stringWithFormat:#"attachment[%i]", counter]
fileName:[dic objectForKey:#"name"]
mimeType:#"image/jpg"];
counter++;
}
}];
RKObjectRequestOperation *operation = [[RKObjectManager sharedManager] managedObjectRequestOperationWithRequest:request
managedObjectContext:[NSManagedObjectContext MR_defaultContext]
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
KLog(#"success");
completionHandler((DBTasks *)[mappingResult firstObject], nil);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
KLog(#"fail");
completionHandler(nil, error);
}];
[operation start];
}
It seems attachments are added per request, not per object. Now when I am POSTing an array of objects instead of single object, how can I add attachments with each object? So that server could decide which attachment is added for which object.

How to save to Core Data RKMappingResult object in RestKit?

I try to save to Core Data NSManagedObject which I got from server. But I don't know any idea how to save object got from [mappingResult firstObject] in success block to Core Data. How can I do this? Should I use RKObjectManager's postObject or RKManagedRequestOperation? Should I do [managedObjectContext insertNewObjectForEntityForName:#""] before this?I can't find any instructions in official docs for this case and need some help.
**EDIT: **I initialise RKManagedRequestOperation like this:
RKResponseDescriptor* responseDescriptor =[RKResponseDescriptor
responseDescriptorWithMapping:[UserMapping mappingForUser]
method:RKRequestMethodPOST
pathPattern:kUserEndpoint
keyPath:#"profile"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKRequestDescriptor* requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[UserMapping mappingForUserProfileModel]
objectClass:[User class] rootKeyPath:#"profile" method:RKRequestMethodPOST];
[[RKObjectManager sharedManager] addRequestDescriptor:requestDescriptor];
[[RKObjectManager sharedManager] addResponseDescriptor:responseDescriptor];
userObject = [User new];
NSDictionary* userParameters = #{ #"user_id" : [User sharedUser].userId};
[[RKObjectManager sharedManager] appropriateObjectRequestOperationWithObject:resumeObject method:RKRequestMethodPOST
path:kUserEndpoint
parameters:userParameters];
RKManagedObjectRequestOperation* managedRequest = [[RKManagedObjectRequestOperation alloc]
initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#", kService, kUserEndpoint]]]
responseDescriptors:#[responseDescriptor]];
managedRequest.managedObjectContext = _managedObjectContext;
[managedRequest setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"MAPPING = %#", [mappingResult firstObject]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
[[RKObjectManager sharedManager] enqueueObjectRequestOperation:managedRequest];
EDIT2: RestKit doesn't save mapped data to CoreData. But userObject.title saves perfectly:
userObject = [_managedObjectContext insertNewObjectForEntityForName:#"User"];
userObject.title = #"USER_NAME";
NSDictionary* userParameters = #{ #"user_id" : [User sharedUser].userId};
[[RKObjectManager sharedManager] postObject:userObject path:kUserEndpoint parameters:userParameters
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
} failure:^(RKObjectRequestOperation *operation, NSError *error) { }];
You need to take a step back as your suggestions are shooting in the dark.
If you configure your object manager with a managed object store and create response descriptors with entity mappings then when you receive data as a result of requests this will be converted into managed objects. These objects will automatically be saved to the core data store before the success block is called.
Any other objects you want to create can be created as usual and you need to explicitly save the context.
Sending requests with RestKit doesn't itself change the store contents, only the response results in changes.
See this tutorial. There is an example of using RestKit with object management and Code Data
https://github.com/alexanderedge/RestKitTutorial1

RestKit 0.20 Ignore putObject: mapping

I'm trying to send an object to the server (PUT request) without a mapping because I already have everything I need from the server. The callback directly goes to failure, even though the server has sucessfully created the object.
Here is an example of what I am doing:
- (void) PUTsuccess:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success
failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure
{
RKObjectManager *objectManager = [YSManager objectManager];
[objectManager putObject:self path:[kPutPath stringByAppendingString:self.id] parameters:kAPIDefaultParameters success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"operation.HTTPRequestOperation.request.HTTPBody: %#", [[NSString alloc] initWithData:operation.HTTPRequestOperation.request.HTTPBody encoding:NSUTF8StringEncoding]);
if (success) {
success(operation, mappingResult);
}
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"Failure! Error: %#", error.localizedDescription);
if (failure) {
failure(operation, error);
}
}];
}
The server response is 201 created and I can find back my object in the server so that's all good, but still, the callback directly fires failure because it's trying to map my object, the error in the failure callback is:
Error: No response descriptors match the response loaded.
Thanks a lot, any suggestion will be appreciated!
Update 1
Added dictionary mapping now:
RKObjectMapping *idMapping = [RKObjectMapping requestMapping];
[idMapping addAttributeMappingsFromArray:#[]];
RKResponseDescriptor *responseDescriptorID = [RKResponseDescriptor responseDescriptorWithMapping:idMapping
pathPattern:[kRequestPath stringByAppendingString:#":code"]
keyPath:#"objects"
statusCodes:statusCodes];
Define a response descriptor simply to map the response (or part of it) to an NSDictionary.

Objective-c + RestKit - Wait for response before next step

Hello and thanks in advance for your help. I've been looking but couldn't find an answer for this. I've only been programing for iOS for a week.
So far, all the connections to the web services are functioning and I've created a class and methods to do those calls. I'm making a standard login, user enters login info, the app passes those values to the web service and it returns a bool value depending if the info matches anything on the database. After that, the app gets the return value and it moves to the next screen or shows an error alert. Or at least that's what I'm aiming for.
The problem is that, the conditional is being executed before the rest call is made or the response parsed and I'm not having much luck finding a solution. I've read about asynchronous and synchronous calls but hadn't have much luck at implementing them.
This is the call code:
//Class that has the methods for calling the web services
__restObj = [[restCalls alloc] init];
bool login = [__restObj restLogin:user passwd:pass];
if (login) {
[self performSegueWithIdentifier:#"adminLogin" sender:self];
}
else{
UIAlertView*alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Incorrect group name or password." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
The conditional in being performed before the actual POST occurs and there for is always false.
This is my method:
- (bool)restLogin:(NSString*)user passwd:(NSString*)pass{
// Load the object model via RestKit
RKObjectManager *objectManager = [RKObjectManager sharedManager];
groupInfo *gi = [[groupInfo alloc] init];
gi.gName = user;
gi.pass = pass;
RKObjectMapping *userInfoMapping = [RKObjectMapping requestMapping];
[userInfoMapping addAttributeMappingsFromDictionary:#{#"gName": #"groupName",#"pass":#"pass"}];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:userInfoMapping
objectClass:[groupInfo class]
rootKeyPath:nil];
[objectManager addRequestDescriptor:requestDescriptor];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager postObject:gi
path:#"adminLoginIos"
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSArray* statuses = [mappingResult array];
NSLog(#"Loaded statuses: %#", statuses);
_result = [statuses objectAtIndex:0];
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"Hit error: %#", error);
}
];
return _result;
}
Thanks in advance and keep in mind that I'm really new at this so I appreciate your help and if my code is not the best please tell me so.
Regards,
ChmlGr
You need to pass in a block and then inside the success callback, block return the _result.
An example based on your structure would be something like:
-(void) restLogin:(NSString*)user passwd:(NSString*)pass block:(void (^)(id))block {
// Load the object model via RestKit
RKObjectManager *objectManager = [RKObjectManager sharedManager];
groupInfo *gi = [[groupInfo alloc] init];
gi.gName = user;
gi.pass = pass;
RKObjectMapping *userInfoMapping = [RKObjectMapping requestMapping];
[userInfoMapping addAttributeMappingsFromDictionary:#{#"gName": #"groupName",#"pass":#"pass"}];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:userInfoMapping
objectClass:[groupInfo class]
rootKeyPath:nil];
[objectManager addRequestDescriptor:requestDescriptor];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager postObject:gi
path:#"adminLoginIos"
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSArray* statuses = [mappingResult array];
NSLog(#"Loaded statuses: %#", statuses);
_result = [statuses objectAtIndex:0];
block(_result);
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"Hit error: %#", error);
block(nil);
}
];
}
Your call to that method would be something like:
[__restObj restLogin:user passwd:pass block:^(id obj) {
// do something here to translate that object into a BOOL and check value
}];
I don't use RestKit, so I can't verify this is exactly what you need, but it should get you on the right path. That said, if you wanted to check out AFNetworking, I wrote a NetworkClient wrapper that I don't mind sharing.

Resources