get method using RKObjectManager instead of RKRequestOperation - RestKit - ios

Below is the function which uses RKObjectRequestOperation for get method how to write the same using RKObjectManager
NSString *hostName = [NSString stringWithFormat:#"%#",[self getHostName]];
NSString *urls = [[NSString alloc] initWithFormat:#"%#/randomcollection/%#/0/%li",hostName,profileId,(long)noOfItems];
RKObjectMapping *responseMapping = [MappingProvider collectionMapping ];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
NSURL *URL = [NSURL URLWithString:urls];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL cachePolicy:NSURLCacheStorageAllowedInMemoryOnly timeoutInterval:90.0f];
[request setValue:[GameManager sharedInstance].authenticatedUser.appTokenId forHTTPHeaderField:#"tokenId"];
RKObjectRequestOperation *objectRequestOperation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[ responseDescriptor ]];
[objectRequestOperation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
if (success) {
RKLogInfo(#"Load collection: %#", mappingResult.array);
}
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
if (failure) {
failure(operation, error);
}
}];
[objectRequestOperation start];
Edit: Here's what I have tried it gives me error of * Assertion failure in -[RKRouter URLWithRoute:object:]
NSString *hostName = [NSString stringWithFormat:#"%#",[self getHostName]];
NSString* urls = [[NSString alloc] initWithFormat:#"%#/userprofile/selectbyid/%#",hostName,profileId];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:urls]];
[manager.HTTPClient setDefaultHeader:#"tokenId" value:[GameManager sharedInstance].authenticatedUser.appTokenId];
RKObjectMapping *responseMapping = [MappingProvider userProfileRespMapping ];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodGET pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[manager addResponseDescriptor:responseDescriptor];
UserProfile * modelObject = [[UserProfile alloc] init];
[modelObject setProfileId:profileId];
[[RKObjectManager sharedManager] getObject:modelObject
path:nil
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
if (success) {
RKLogInfo(#"Load collection of Userprofiles: %#", mappingResult.array);
NSLog(#"Mapping Results %#",[mappingResult.array firstObject]);
UserProfile *currentUserProfile = (UserProfile *)[mappingResult.array firstObject];
success(currentUserProfile);
}
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
if (failure) {
RKLogError(#"Operation failed with error: %#", error);
failure(operation, error);
}
}];

It's very simple. It should look like this. This will give you a starting point. For a more detailed answer you should concretize your question.
// Initial setup
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"your base url"]];
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:modelClass];
[mapping addAttributeMappingsFromDictionary:#{#"sourceProperty" : #"destinationProperty"}];
[manager addResponseDescriptor:
[RKResponseDescriptor
responseDescriptorWithMapping:mapping
method:RKRequestMethodGET
pathPattern:#"yourPath"
keyPath:#"jsonStructureDepending"
statusCodes:
RKStatusCodeIndexSetForClass(
RKStatusCodeClassSuccessful)]];
[[manager router].routeSet
addRoutes:#[
[RKRoute routeWithClass:[model class]
pathPattern:#"yourPath"
method:RKRequestMethodGET]];
//Within your controller or elsewhere
[[RKObjectManager sharedManager] getObject:modelObject
path:nil
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];

Related

Restkit metadata isn't mapping

I'm struggling to get proper mapping with metadata... Everything maps perfectly except metadata url parameters.
Here's my Entity Mapping :
RKEntityMapping *statisticsMapping = [RKEntityMapping mappingForEntityForName:#"Statistics" inManagedObjectStore:managedObjectStore];
[statisticsMapping addAttributeMappingsFromArray:#[#"fromDate", #"toDate", #"visits", #"newVisits"]];
[statisticsMapping addAttributeMappingsFromDictionary:#{
#"#metadata.routing.parameters.randomId" : #"applicationRandomId"
}];
[statisticsMapping addConnectionForRelationship:#"application" connectedBy:#"applicationRandomId"];
Response descriptor:
RKResponseDescriptor *ststResp = [RKResponseDescriptor responseDescriptorWithMapping:statisticsMapping
method:RKRequestMethodGET
pathPattern:#"api/apps/:randomId/statistics"
keyPath:#"details"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
Routing:
[objectManager.router.routeSet addRoute:[RKRoute routeWithClass:[Statistics class] pathPattern:#"api/apps/:randomId/statistics" method:RKRequestMethodGET]];
And how I get them:
NSString *url = [NSString stringWithFormat:#"/api/apps/%#/statistics",applicationRandomId];
NSMutableURLRequest *statistics = [[RKObjectManager sharedManager] requestWithObject:#"Statistics" method:RKRequestMethodGET path:url parameters:#{
#"fromDate" : #"01-01-2016",
#"toDate" : #"20-01-2016"
}];
RKObjectRequestOperation *operation = [[RKObjectManager sharedManager] managedObjectRequestOperationWithRequest:statistics managedObjectContext:[RKManagedObjectStore defaultStore].mainQueueManagedObjectContext success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
I also tried mix with variety of Routes and getObjectsAt etc...
Regards, Adrian.
Solution :
[objectManager.router.routeSet addRoute:[RKRoute routeWithName:#"statistics" pathPattern:#"api/apps/:randomId/statistics" method:RKRequestMethodGET]];
[[RKObjectManager sharedManager] getObjectsAtPathForRouteNamed:#"statistics" object:#{#"randomId" : applicationRandomId} parameters:nil
} success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
Eh didn't know it works that way.

RestKit simple JSON, bad pathPAttern?

JSONs:
http://krzysztofkurzawa.com/articles/
http://krzysztofkurzawa.com/articles/1
Code:
NSURL *baseURL = [NSURL URLWithString:#"http://www.krzysztofkurzawa.com"];
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL];
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping addAttributeMappingsFromArray:#[#"title"]];
RKResponseDescriptor *rk = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:#"articles" keyPath:#"articles" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:rk];
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping addAttributeMappingsFromArray:#[#"title"]];
RKResponseDescriptor *rk2 = [RKResponseDescriptor responseDescriptorWithMapping:mapping2 pathPattern:#"articles/:id" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:rk2];
[[RKObjectManager sharedManager] getObjectsAtPath:#"articles" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"%#", [mappingResult firstObject]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
[[RKObjectManager sharedManager] getObjectsAtPath:#"articles/1" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"%#", [mappingResult firstObject]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
Error: No mappable object representations were found at the key paths
searched.", keyPath=null, NSLocalizedDescription=No response
descriptors match the response loaded.}
I haven't got any ideas. The first mapping works, when pathPattern is set to nil. Why must it be nil? Maybe it is needed for creating rest path patterns.
Your paths were not correct, also, when running your code I had to use the method:
+ (instancetype)responseDescriptorWithMapping:(RKMapping *)mapping
method:(RKRequestMethod)method
pathPattern:(NSString *)pathPattern
keyPath:(NSString *)keyPath
statusCodes:(NSIndexSet *)statusCodes
The one you are using it says it's deprecated. I guess you might be using an old version of restkit.
Here is the code that works:
NSURL *baseURL = [NSURL URLWithString:#"http://www.krzysztofkurzawa.com"];
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL];
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping addAttributeMappingsFromArray:#[#"title"]];
RKResponseDescriptor *rk = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodGET pathPattern:#"/articles/" keyPath:#"articles" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:rk];
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping2 addAttributeMappingsFromArray:#[#"title"]];
RKResponseDescriptor *rk2 = [RKResponseDescriptor responseDescriptorWithMapping:mapping2 method:RKRequestMethodGET pathPattern:#"/articles/:id/" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:rk2];
[[RKObjectManager sharedManager] getObjectsAtPath:#"/articles/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"%#", [mappingResult firstObject]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
[[RKObjectManager sharedManager] getObjectsAtPath:#"/articles/1/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"%#", [mappingResult firstObject]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
May be this halp you
NSString *pathNotation = #"/Notations/:notation_id";
RKRoute *notationRoute = [RKRoute routeWithClass:[Notation class] pathPattern:pathNotation method:RKRequestMethodGET];
[self.objectManager.router.routeSet addRoute:notationRoute];
RKResponseDescriptor *notationMappingDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:notationMapping method:RKRequestMethodGET pathPattern:pathNotation keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
and GET:
[[RKObjectManager sharedManager] getObject:nil path:path parameters:params success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
//do something
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
//do something
}];

ios RestKit post attached UIImage

I am trying to post an image to my server using RestKit and map response from server. But server always back that file I am sending is nil.
Could anyone help me with that issue?
NSData *data = UIImageJPEGRepresentation(imageData, 1.0);
NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:
data, #"avatar",
nil];
RKObjectMapping* objectMapping = [RKObjectMapping mappingForClass:[UpdateAvatar class]];
[objectMapping addAttributeMappingsFromDictionary:#{
#"message" : #"message"
}];
NSIndexSet *successStatusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:objectMapping
method:RKRequestMethodPOST
pathPattern:nil
keyPath:nil
statusCodes:successStatusCodes];
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[self defineBaseUrl]];
[[objectManager HTTPClient] setDefaultHeader:#"device_uid" value:[self getDeviceUid]];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"image/jpeg"];
[objectManager setAcceptHeaderWithMIMEType:#"multipart/form-data"];
[objectManager setRequestSerializationMIMEType:RKMIMETypeJSON];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager postObject:nil path:#"/api/upload-avatar" parameters:params success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"%#", mappingResult.array);
for (UpdateAvatar *obj in mappingResult.array) {
NSLog(#"MESSAGE: %#", obj.message);
[[DataManager sharedManager] setMessage:obj.message];
}
[SVProgressHUD showSuccessWithStatus:#"Profile Picture Updated"];
//[[NSNotificationCenter defaultCenter] postNotificationName:#"didRegistered" object:nil];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"%#", error);
}];
I have solved my issue with Documentation from RESTKit itself.
Maybe it will help to someone else:
NSData *data = UIImageJPEGRepresentation(imageData, 0.3);
RKObjectMapping* objectMapping = [RKObjectMapping mappingForClass:[UpdateAvatar class]];
[objectMapping addAttributeMappingsFromDictionary:#{
#"message" : #"message"
}];
NSIndexSet *successStatusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:objectMapping
method:RKRequestMethodPOST
pathPattern:nil
keyPath:nil
statusCodes:successStatusCodes];
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[DataManager defineBaseUrl]];
[[objectManager HTTPClient] setDefaultHeader:#"device_uid" value:[self getDeviceUid]];
[objectManager addResponseDescriptor:responseDescriptor];
NSMutableURLRequest *request = [[RKObjectManager sharedManager] multipartFormRequestWithObject:nil method:RKRequestMethodPOST path:#"/api/upload-avatar" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:data
name:#"avatar"
fileName:#"image.jpeg"
mimeType:#"image/jpeg"];
}];
RKObjectRequestOperation *operation = [objectManager objectRequestOperationWithRequest:request success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
for (UpdateAvatar *obj in mappingResult.array) {
[SVProgressHUD setBackgroundColor:[UIColor colorWithRed:0.31 green:0.31 blue:0.31 alpha:0.5]];
[SVProgressHUD setRingThickness:2];
[SVProgressHUD setForegroundColor:[UIColor whiteColor]];
[SVProgressHUD showSuccessWithStatus:[NSString stringWithFormat:#"Uploading avatar\n %#", obj.message]];
}
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"Failure");
}];
[[RKObjectManager sharedManager] enqueueObjectRequestOperation:operation];

RestKit 2 PUT request for some Object

Server team wants to separate out 2 PUT requests for one Item class like this -
PUT '<server>/item/:itemId'
and
PUT '<server>/item/:itemId/like'
I am using the following code in the initializer:
RKObjectManager *sharedRKObjectManager = [RKObjectManager sharedManager];
RKManagedObjectStore *managedObjectStore = [sharedRKObjectManager managedObjectStore];
// Create the mapping for the News entity.
RKEntityMapping *responseMapping = [RKEntityMapping mappingForEntityForName:ENTITY_ITEM inManagedObjectStore:managedObjectStore];
[responseMapping addAttributeMappingsFromDictionary:#{
#"id": #"itemId",
}];
// Create a response descriptor and add it to the RKObjectManager object.
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping
method:RKRequestMethodAny
pathPattern:UPDATE_ITEM_URL
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[sharedRKObjectManager.router.routeSet addRoute:[RKRoute routeWithClass:[Item class] pathPattern:UPDATE_ITEM_URL method:RKRequestMethodAny]];
[sharedRKObjectManager addResponseDescriptor:responseDescriptor];
And then the following is the call:
+(void)updateItem:(Item*)item
withParams:(NSDictionary*)params
success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success
failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure
{
[CMLRKSharedManager setUpHeaders];
[[RKObjectManager sharedManager] putObject:item path:nil parameters:params success:success failure:failure];
}
My ques is - can i use the same functions for these 2 requests? Can i append the url any other way?
TIA!
Just don't use the RKRoute in this case. Explicitly supply the appropriate path when you call put....
Note that you should also have 2 response descriptors because the path patterns are different.
in case it helps anyone.. here is the code to do this
NSString *path = [NSString stringWithFormat:#"item/%#/like", itemId];
[CMLRKSharedManager updateItem:item params:nil path:path success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"Displaying user info %#", [mappingResult firstObject]);
} failure:nil];

RESTKit 2.0: Pattern string must not be empty in order to perform pattern matching

I use the code below to login to the server:
//First Block Code
-(RKObjectManager *)getObjectManager
{
NSURL *baseURL = [NSURL URLWithString:#"http://api.domain.com"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc]initWithBaseURL:baseURL];
RKObjectManager *manager = [[RKObjectManager alloc]initWithHTTPClient:httpClient];
[manager.HTTPClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[manager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[manager.HTTPClient setParameterEncoding:AFJSONParameterEncoding];
[RKMIMETypeSerialization registeredMIMETypes];
return [RKObjectManager sharedManager];
}
- (void)loginUserwithUsername:(NSString *)username andPassword:(NSString *)password requestByNewUser:(BOOL)newRegistration
{
[self getObjectManager];
RKObjectManager *objectManager = [RKObjectManager sharedManager];
[objectManager.HTTPClient setAuthorizationHeaderWithUsername:username password:password];
NSIndexSet *statusCodeSet = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKMapping *mapping = [RESTMappingProvider profileMapping];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:nil statusCodes:statusCodeSet];
NSMutableURLRequest *request = [objectManager.HTTPClient requestWithMethod:#"POST"
path:#"/login"
parameters:#{#"username": username,
#"password": password
}];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request
responseDescriptors:#[responseDescriptor]];
[objectManager.HTTPClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"mappingResults Error %#", error);
}
}];
[operation start];
}
AFTER I login, I try to make a Google Places API request and get an error:
//Second Block of Code
- (void)fetchPlaces:(NSString *)input;
{
NSIndexSet *statusCodeSet = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKMapping *mapping = [RESTMappingProvider googleAutoCompleteMapping];
NSString *urlString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/json?input=%#&sensor=true&key=%#&location=0.000000,0.000000", input, self.key];
NSString *urlStringEncoded = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlStringEncoded];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:#"predictions" statusCodes:statusCodeSet];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request
responseDescriptors:#[responseDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
self.responseObjects = mappingResult.array;
[operation start];
}
Error:
2014-04-02 14:11:17.865 App[1247:60b] *** Assertion failure in +[RKPathMatcher pathMatcherWithPattern:], /Users/App
Time/Pods/RestKit/Code/Support/RKPathMatcher.m:74
2014-04-02 14:11:17.868 App[1247:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Pattern string must not be empty in order to perform pattern matching.'
However, if I never Login (meaning that I skip the first code in this question) and go straight to call Google API, there is no crash API works great.
I think there is something that I'm doing to RESTKit (perhaps by creating an ObjectManager), by Logging-in that's causing Google's API call to cause a crash.
I tried to run Charles Web Debug Proxy, but the crash seems to happen even before making the API call.
*EDIT *
I found out what is causing the crash:
[[RKObjectManager sharedManager] cancelAllObjectRequestOperationsWithMethod:RKRequestMethodAny matchingPathPattern:nil];
This was an attempt to Cancel all previous requests.
I replaced it with:
[[RKObjectManager sharedManager] cancelAllObjectRequestOperationsWithMethod:RKRequestMethodAny matchingPathPattern:#"maps/api/place/autocomplete"];
and it seems to work.
Question: Does this code cancel any previous request to: https://maps.googleapis.com/maps/api/place/autocomplete/json ?
When you create responseDescriptor this is added to the RKObjectManager you use pathPattern:nil. This is not permitted. You must specify a path pattern as RestKit must lookup the appropriate response descriptor to apply to the received response.
Later, you again use pathPattern:nil, but this is directly with an RKObjectRequestOperation. In this case it is allowed (and thus works) because you have provided an explicit list and no lookup is required.

Resources