RestKit GET request works just once - iphone

I'm using Restkit to communicate with Java Jersey REST server. I'm using a very simple method available on RKClient class, which is:
[[RKClient sharedClient] get:#"/userStatus" delegate:self];
The created methods in mw class are:
- (void)sendRequests
{
[[RKClient sharedClient] get:#"/userStatus" delegate:self];
}
- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response
{
if ([request isGET])
{
if ([response isOK])
{
NSLog(#"Retrieved status: %#", [response bodyAsString]);
}
}
}
The problem is that I want to execute this GET several times, but it appears to work just once. Am I doing something wrong?

It is working now! I really don't know which change I made to get it working. Probably the problem was the Jersey server. After modifying the GET method and adding some parameters to it (after all I figured out I needed some parameters to identify some resources) it started to work. Thank you anyway for the help.

Related

Check if the current request is already in request queue using restkit iphone

I am using restkit for sending request, response mapping and all. but sometimes, i am sending same request multiple time which comes from different screens. So it get added to request queue. But i don't want to add request into request queue if the request is already there. How can i check that.
I am calling function like this
//Here I need to check if the following url is in RKRequestQueue. If it not there then call the below method,
[self getDataFromServer];
- (void)getDataFromServer{
RKObjectManager *manager = [[RestKit sharedDataManager] objectManager];
[manager loadObjectsAtResourcePath:#"/getData" usingBlock:^(RKObjectLoader *loader) {
[RKClient sharedClient].requestQueue.showsNetworkActivityIndicatorWhenBusy = YES;
loader.method = RKRequestMethodPOST;
loader.params = inputData;
loader.onDidFailWithError = ^(NSError *error) {
};
loader.onDidLoadObjects = ^(NSArray *objects) {
};
}
Any help is appreciated.
Interesting question, I was pretty sure that you can actually check the URLs of your requests in the RKRequestQueue, but I wasn't able to find anything useful for that in the RKRequestQueue reference. Instead, I've found the containsRequest: method, but this will only compare RKRequest objects, not the actual URLs.
I guess the simplest thing to do is to create some kind of proxy for managing your network activity, implement the requestQueue:didSendRequest: delegate method and monitor which URLs are currently processed.

How to parsing XML simultaneously from URLS in iphone

I have about 15 URLs for XML Parsing simultaneously. I am using KMXML Parser for XML parsing.
How can i do Parsing simultaneously using thread. How to handle the responses form that parsing. How can i store those responses in Sq-lite Database.
My code for parsing is as follow:
NSArray* yourURLs = [NSArray arrayWithObjects:#"http://www.designworldonline.com/rss/",#"http://www.3dcadtips.com/feed/",#"http://feeds.feedburner.com/MakePartsFast",#"http://www.designworldonline.com/category/technologies/electricalelectronic/feed", nil];
for(NSString* url in yourURLs) {
[self performSelectorInBackground:#selector(parse:) withObject:url];
}
-(void)parse:(NSString*)link {
KMXMLParser *parser = [[KMXMLParser alloc] initWithURL:link delegate:self];
_parseResults = [parser posts];
[self performSelectorOnMainThread:#selector(update) withObject:_parseResults waitUntilDone:NO];
}
-(void)update
{
[pd addObject:_parseResults];
}
But with this coding,
_parseresults=[parser posts]; is called only for last link rather than for each link.
and i got response in array pd is only from last link & 9 times. i don't know why parsing method is only called last time only.
try to use framework will help you very will
https://github.com/AFNetworking/AFNetworking
https://github.com/pokeb/asi-http-request
Use Operation Queue and then add all your operations inside Operation Queue.
Check out this link ...
http://developer.apple.com/library/mac/#samplecode/NSOperationSample/Introduction/Intro.html%23//apple_ref/doc/uid/DTS10004184
hope it will help
Happy Coding.

how call nsurlconnection delegate methods continuosly in iphone

hi in one of my application. i have to send a request to the server (json server) many times continously.my url will be like this as mention below
#"http://185.185.116.51/servername/serverjspfilesname.jsp?filterID=21&ticket=65675656565656567"
actually i have many filter id's (filter id you can find at top).in order to chnage the filterid continously i used for loop like this as mention below
for(int i=0;i<[appdelegate.listOfFiltersArray count];i++)
{
filtersDataModelObject=[[ListOfFiltersDataModel alloc]init];
filtersDataModelObject=[appdelegate.listOfFiltersArray objectAtIndex:i];
homescreenstring=[NSString stringWithFormat:#"http://%#/servername/serverjspfilesname.jsp?filterID=%#&ticket=%#",Ip,filtersDataModelObject.filterID,[storeData stringForKey:#"securityTicket"]];
NSLog(#"url is %#",homescreenstring);
NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:homescreenstring]];
connection=[[NSURLConnection alloc]initWithRequest:request delegate:self];
if(connection)
{
homeScreenResponseData=[[NSMutableData alloc]init];
}
else
{
NSLog(#"connection failed");
}
}
actually after each condition is satisfied in for loop i have to connect with the server for getting the data from the server using nsurlconnection delegate methods. but here after complete execution of for loop only nsurlconnection delegate methods are executing with last filterid which is getting from the appdelegate.listOfFiltersArray array.
but i would like to call the server for each filterid.
if anyone know please let me know.thanks in advance.
Create one count variable int count in .h file.
int count = 0 //in .m file
Now use this method:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//one request finished
count ++;
//request another using count
}
The solution that Prince proposed is not general as you will face the problem of defining the
"filterid" for each request.
And what you are doing is a bad approach. Dont mix the web request with your business logic code.The web stuff should be handled by a separate file handling all the requests throughout the app. And that class will implement delegation.
For delegation you need to do the following.
In your Network class header (Networkclass.h) add the protocol
#protocol NetworkControllerDelegate <NSObject>
-(void) UrlResponseRecieved :(NSData *)responseData;
-(void) UrlResponseFailed:(NSError *)error;
#end
and in NetworkClass.m (implementation fie) do the following
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (receivedData != nil)
{
if([delegate respondsToSelector:#selector(UrlResponseRecieved:)])
[self.delegate UrlResponseRecieved:receivedData];
[receivedData release];
receivedData = nil;
}
[connection release];
}
if you still get stuck you may refer to the following
What's wrong on following URLConnection?
or you may read any asynchronous downloading tutorial first.

Detect a redirect in RestKit not working?

I have a web service returning a 302 and the automatic redirect is done by RestKit. I'm trying to do extra logic before the redirect. I know RestKit has isRedirect and isRedirection. So in the request:didLoadResponse delegate I tried to check for it, but it doesn't seem to be hitting any of those. Is there something I'm missing?
- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response
{
if ([response isRedirection])
{
NSLog(#"redirection");
}
else if ([response isRedirect])
{
NSLog(#"redirect");
}
NSLog(#"response %#", [response bodyAsString]);
}
Solved this by implementing this:
#implementation RKResponse (CustomRedirect)
- (NSURLRequest *)connection:(NSURLConnection *)inConnection willSendRequest:(NSURLRequest *)inRequest redirectResponse:(NSURLResponse *)inRedirectResponse
{
NSLog( #"redirectResponse ***********************************************");
NSURLRequest *newRequest = inRequest;
if (inRedirectResponse) {
newRequest = nil;
}
return newRequest;
}
#end
This basically says you want to handle the redirect yourself since you are returning nil. Now the checks for isRedirect and isRedirection will be hit.
I've found an alternative to kailoon way that shoud be a little less "code invasive" for everyone having problems with that solution.
use
[request setFollowRedirect:NO]
and you should be able to trap the 302 in the requestDidReceiveResponse callback.
It worked for me.
An old thread, I know, but just in case anyone comes looking. If you're using RKObjectManager, you can implement setRedirectResponseBlock in order to ignore/modify redirects:
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:url];
RKObjectRequestOperation *operation = [objectManager objectRequestOperationWithRequest:request ...etc...];
[operation.HTTPRequestOperation setRedirectResponseBlock:^NSURLRequest *(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse) {
return redirectResponse ? nil : request;
}];
[objectManager enqueueObjectRequestOperation:operation];
Seems to do the trick.

AFNetworking HTTPClient subclass with XMLParser

I am writing a small iOS app that queries a XML REST webservice. The networking framework in use is AFNetworking.
Situation
To query the webservice I subclassed AFHTTPClient:
#interface MyApiClient : AFHTTPClient
and in the implementation I make that available as a singleton:
+ (MyApiClient *)sharedClient {
static MySharedClient *_sharedClient = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedClient = [[self alloc] initWithBaseUrl:[NSUrl URLWithString:#"http://url.to.the.webservice"]];
});
return self;
}
and in initWithBaseURL I tell AFNetworking to expect XML content:
[self registerHTTPOperationClass:[AFXMLRequestOperation class]];
Now I can call getPatch on the singleton from my ViewController and in the success block start parsing my returned XML. In NSXMLParserDelegate methods in the ViewController I can then pick the parts of the XML I am interested in and do stuff with it.
Problem
I want to have methods in my HTTPClient singleton that handle everything related to the webservice and return data models or list of models instead of XML.
For example I want to do something like this:
ServerModel *status = [[MyApiClient sharedClient] getServerStatus];
The ApiClient would then internally call the webservice, parse the XML and return the model.
How can I do that? Normally I would use a delegate that gets called once the XML is parsed, but due to the singleton nature of the ApiClient there could be multiple delegates?
Hope someone can shed light on this, thanks!
Use blocks instead of delegates.
From my ApiClient class:
- (void)getPath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id response))success
failure:(void (^)(NSError *error))failure
{
NSURLRequest *request = [self requestWithMethod:#"GET" path:path parameters:parameters];
[self enqueueHTTPOperationWithRequest:request success:success failure:failure];
}
-(void)fetchAllUsersSuccess:(void (^)(id))success
failure:(void (^)(NSError *))failure
{
[self getPath:#"/api/mobile/user/"
parameters:nil
success:^(id response) {
if([response isKindOfClass:[NSXMLParser class]]){
//parse here to new dict
success(newDict);
} else
success(response);
} failure:^(NSError *error) {
failure(error);
}];
}
Now I can use it like:
ServiceApiClient *apiClient = [ServiceApiClient sharedClient];
[apiClient fetchAllUsersSuccess:^(id dict) {
for (NSDictionary *object in [dict objectForKey:#"objects"]) {
[ServiceUser addUserFromDictionary:object
inContext:self.managedObjectContext];
}
NSError *error= nil;
[self.managedObjectContext save:&error];
if (error) {
NSLog(#"%#", error);
}
} failure:^(NSError * error) {
NSLog(#"%#", error);
}];
(Apologies in advance for this "sort-of" answer, but we're working towards a better solution...)
You need to take a step back and think about your design carefully.
You're having problems because you've got an idea that something in your design needs to be a singleton, but either:
1) that's not actually necessary,
2) something might already exist that does that job for you (e.g. the HTTP lib you're using),
or
3) You're making the wrong thing a singleton, or you haven't portioned out your design into the appropriate parts to work well with the singleton idea
So, can you tell me explicitly why you're going for a singleton approach? Is it just to ensure that only one network request can happen at once? Is there any notion of statefulness in your singleton object? Then I'll update this answer or comment, etc.
(Digression: I would also add that in some cases there might be a true need for a 'strong' singleton -- by which I mean that there really is only one possible instance, and that mechanism is baked right into your object, as you are doing - but this isn't it. The alternative is a 'weak' singleton, by which I mean your core object that actually does the work has a plain init method as usual, but shared access to a common object goes via another object, which is a kind of simple 'factory' that instantiates/holds the shared instance. The advantage of this weak singleton idea is that your code is more re-usable in different contexts - e.g. you could decide to do multiple HTTP requests/sessions concurrently at a later time - and it sometimes makes writing tests less problematic).