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];
Related
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];
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];
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) {
}];
I am trying to add a custom header to all the http request from the app but on server side I am not getting it.
I tried following methods:
1.setting header in NSMutableURLRequest:
[request addValue:headerString forHTTPHeaderField:#"deviceDetails"];
NSLog( #"%#",[request valueForHTTPHeaderField:#"deviceDetails"]);
Here I get null just after setting the header value. Not sure what is happening.
2.setting default header in RKObjectManager
[manager.HTTPClient setDefaultHeader:#"deviceDetails" value:headerString];
Here header seems to be set but on server there is no header field with key "deviceDetails"
Any help would be appreciated.
Code:
NSMutableURLRequest *request =[self _createPostRequestWithParams:[NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:nil] andPath:path];
[request setTimeoutInterval:20];
NSLog(#"%#",[request valueForHTTPHeaderField:#"deviceDetails"]);
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:BASE_URL]];
[manager setRequestSerializationMIMEType:#"application/json"];
[manager.HTTPClient setAuthorizationHeaderWithUsername:self.offlineService.user.username password:self.offlineService.user.password];
[manager addResponseDescriptor: [self _getResponseDescriptorWithKeyPath:keyPath andResponseClass:responseClass]];
[manager.HTTPClient setDefaultHeader:#"deviceDetails" value:#"String value" encoding:NSUTF8StringEncoding]];
RKObjectRequestOperation *operation = [self _createOperationForRequest:request successcallback:requestSuccessful failurecallback:requestFailure target:target manager:manager];
[operation start];
_createOperationForRequest:
- (RKObjectRequestOperation *)_createOperationForRequest:(NSMutableURLRequest *)request successcallback:(SEL)requestSuccessful failurecallback:(SEL)requestFailed target:(id)target manager:(RKObjectManager *)manager {
RKObjectRequestOperation *operation = [manager objectRequestOperationWithRequest:request
success:^(RKObjectRequestOperation *operation,RKMappingResult *result) {
}
failure:^(RKObjectRequestOperation *operation,NSError *error){
}];
return operation;
}
In above code both basic authentication and device details header are received on the server side.
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.