iOS RestKit loggging doesn't print anything - ios

I would like to user RestKit's network logging with the following code:
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
I am creating GET/POST requests and nothing is printed to the console. I am using Xcode 6.1.1.
Anybody has any clues why it isn't printing anything to the console?
Edit:
RestKit initialization:
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
[RKObjectManager setSharedManager:[RKObjectManager managerWithBaseURL:self.baseURL]];
[[RKObjectManager sharedManager] setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[RKObjectManager sharedManager].requestSerializationMIMEType = RKMIMETypeJSON;
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithPersistentStoreCoordinator:[IPCoreDataHelper sharedInstance].persistentStoreCoordinator];
[managedObjectStore createManagedObjectContexts];
[RKManagedObjectStore setDefaultStore:managedObjectStore];
[RKObjectManager sharedManager].managedObjectStore = [RKManagedObjectStore defaultStore];
[self setMappings];
After this, for example, the user will press the login button and the following code is executed
Login:
// ... Setup the user object
NSMutableURLRequest *urlRequest = [[RKObjectManager sharedManager] requestWithObject:user method:RKRequestMethodPOST path:#"login/" parameters:nil];
urlRequest.timeoutInterval = 300;
RKManagedObjectRequestOperation *operation = [[RKObjectManager sharedManager] managedObjectRequestOperationWithRequest:urlRequest managedObjectContext:[RKManagedObjectStore defaultStore].mainQueueManagedObjectContext success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
// Do something with login success
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
// Failed
}];
[operation start];

Related

Restkit - enqueueObjectRequestOperation not being called after adding rootviewcontroller in appdelegate

I have been using Restkit to connect to my API server, and it works perfectly. Now my situation is that I added a checker in my appdelegate.m in didFinishLaunchingWithOptions. it checks if there is already adminID in the coredata. if there was a adminID stored, when the app is relaunched, it will set the rootviewcontroller into a uinavigation controller. but when the uiviewcontroller is called, the Restkit enqueueObjectRequestOperation is not called.
Here's my code:
in appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//adminID is fetch from custom Entity in core data
if(adminID==0){
AllKommunScreenViewController *adminController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"AllKommunScreenID"];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:adminController];
self.window.rootViewController = navController;
}
return YES;
}
Here's my code in the Navigation controller's Rootview:
-(void)fetchData{
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[Auth class]];
[responseMapping addAttributeMappingsFromArray:#[#"status", #"sucess", #"data"]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *userProfileDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:statusCodes];
NSString *apiPath = [NSString stringWithFormat:#"%#%#", baseURL,#"/api/kommun/all/stats/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:apiPath]];
request setValue:_sharedManager.userAccessToken forHTTPHeaderField:#"X-ACCESS-TOKEN"];
RKObjectRequestOperation *operation =[[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[userProfileDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {} failure:^(RKObjectRequestOperation *operation, NSError *error) {}];
[RKObjectManager sharedManager] enqueueObjectRequestOperation:operation];
}
i called the fetchData in viewWillAppear.
Then i add a breakpoint to the function, and it goes there, the problem is that the restkit is not calling the enqueueObjectRequestOperation.
Please help!!!
By the way, i make a custom core data entity to store the adminID
Why are you calling?
[RKObjectManager sharedManager] enqueueObjectRequestOperation:operation];
I think you should call
RKObjectRequestOperation *operation =[[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[userProfileDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
//print something
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
// print something
}];
[operation start];
If you want to add it to queue of Object Request Operations you should first init RKObjectManager and than call enqueueObjectRequestOperation:
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:baseUrl];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:apiPath]];
request setValue:_sharedManager.userAccessToken forHTTPHeaderField:#"X-ACCESS-TOKEN"];
RKObjectRequestOperation *operation =[[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[userProfileDescriptor]];
[manager enqueueObjectRequestOperation:operation];

get method using RKObjectManager instead of RKRequestOperation - RestKit

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) {
}];

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.

RKObjectManager sharedManager getObjectsAtPath Optionally save in persistent storage

[[RKObjectManager sharedManager] getObjectsAtPath:#"/pathpattern/:userId" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"success");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"fail");
}];
I am using RKManagedObjectStore using addSQLitePersistentStoreAtPath:fromSeedDatabaseAtPath:withConfiguration:options:error
The defined pattern gives different data for different "userId", I want to save data in sqlite data base for only one userId, for other userIds I don't want to save it.
Any suggestion how this could be achieved using same [RKObjectManager sharedManager]
You can use an RKDynamicMapping with the response descriptor for that path. With that mapping you can analyse the incoming data and decide which mapping you actually want to apply to the received data.
Note that 'not saving' the new objects to Core Data means using an RKObjectMapping instead of RKEntityMapping.
you don`t init your shared manager. try this.
NSURL *url = [NSURL URLWithString:yourURL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
RKObjectManager *operation = [[RKObjectManager alloc] initWithHTTPClient:httpClient];
[[RKObjectManager sharedManager] getObjectsAtPath:kURLToDownloadData
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult){
NSLog(#"success");
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"fail");
}

Post JSON Body + MultiPart RestKit 0.2x fails

I am trying to post an object with an attached file.
NSMutableURLRequest *request =
[objectManager multipartFormRequestWithObject:reqDocObj
method:RKRequestMethodPOST
path:#"syncDocument.json"
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:UIImagePNGRepresentation([UIImage imageNamed:#"graybox.png"])
name:#"image"
fileName:#"some_file"
mimeType:#"image/jpeg"];
}];
RKObjectRequestOperation *operation =
[objectManager
objectRequestOperationWithRequest:request
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"WS: errore operazione di richiesta %#",error);
}
];
[objectManager enqueueObjectRequestOperation:operation];
The objectManager is configured as:
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[objectManager setRequestSerializationMIMEType:RKMIMETypeJSON];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[EDIT]
My mapepd object is SynchDocObj:
requestDocMapping = [RKObjectMapping mappingForClass:[SynchDocObj class]];
[requestDocMapping addAttributeMappingsFromDictionary:mappingDocDict];
The problem is:
1) In the RKlogs, the request.body = null and the JSON object is put into the form-data
2) The server cannot decode the body because it is null
My question is:
1) Am I sending the JSON object in the wrong way?
2) If yes, how can I send a JSON object with a file upload, i.e. as a multipart request?
Regards!
[SOLUTION]
Following the suggestion of the answer, I think the solution is 1) retrieve the mapped object from the form-data and not the body ; 2) OR post a nil object and putting a JSON string within the form-data.
This:
[objectManager setRequestSerializationMIMEType:RKMIMETypeJSON];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
is 2 different ways of saying the same thing - and you don't want to have either of them. You need to send the request as form URL encoded (the default value).
The easiest thing to do is to use the same form as in your current code to create the request, generate the JSON earlier and then use appendPartWithFormData:name: to add it to the request (just before you add the file).
To generate the JSON you can use RestKit (RKMappingOperation) or you can just create a dictionary / array of content and then use NSJSONSerialization to serialise that object to be added to the request.
Analyze my code, it works like a charm:
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[FilledExamCard defineMapping] objectClass:[MappedClassName class] rootKeyPath:nil method:RKRequestMethodPUT];
NSData *jsonPayload = [self getJSONpayloadFromObject:mappedClassObject requestDescriptor:requestDescriptor];
NSURL *baseURL = [NSURL URLWithString:[ZDR_BASE_URL stringByAppendingString:#"PutExamCards"]];
AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:baseURL];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"text/plain"];
[client setDefaultHeader:#"Accept" value:#"text/plain"];
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
[objectManager setRequestSerializationMIMEType: RKMIMETypeJSON];
[objectManager addRequestDescriptor:requestDescriptor];
NSMutableURLRequest *request = [objectManager multipartFormRequestWithObject:nil method:RKRequestMethodPUT path:#"" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
// Name may vary depending from server settings
[formData appendPartWithFormData:jsonPayload name:#"model"];
}];
RKObjectRequestOperation *operation = [objectManager objectRequestOperationWithRequest:request success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
// Process data
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
// An error occurred
}];
-(NSData*)getJSONpayloadFromObject:(NSObject*)object requestDescriptor:(RKRequestDescriptor*)requestDescriptor
{
NSDictionary *paramObject = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:paramObject options:NSJSONWritingPrettyPrinted error:&error];
return jsonData;
}

Resources