How to handle different requests using connectionDidFinishLoading in the same delegate? - objective-c

Whenever I do a curl call using the below code:
NSURL *url = [NSURL URLWithString:requestURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:30];
if (connectionInProgress) {
[connectionInProgress cancel];
}
connectionInProgress = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];
connectionDidFinishLoading is my final destination where I can manipulate the response data and call my next methods to continue with the app . If I hard-code some specific tasks like
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
[parser setDelegate:self];
[parser parse];
[someLabel setText:parsedTextFromXMLData];
}
If I need to do another curl call to a different address, wouldn't someLabel setText always get re-set again? Is there a way to make this delegate function behave differently on each curl call? (btw, is connectionDidFinishLoading usually the right place to put the next step of codes?) If so then wouldn't it always get called again by the next curl call?

Have a look at this S.O. post for a recipe concerning NSURLConnection and multiple requests.The suggestion is doing something like this:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (connection == firstConnection) {
// do something
}
else if (connection == secondConnection) {
// do something else
}
}
EDIT: the idea here is that connectionDidFinishLoading is a method of your own delegate (so you write it). In the delegate, you store the address of each connection you create; then, when the connection comes back with the data, you tell which connection it is by comparing its address to the one you stored in the delegate. -END EDIT
Another option you have is using the ASIHTTPRequest framework, which offers a request-based (as opposed to connection-based) delegation mechanism, so each request has got a delegate object to handle the result; or, in other words, the delegate receives a reference to the request, so you can easily tell which request result you are handling.
ASIHTTPRequest offers a bunch of advantages over NSURLConnection. You can read about them in this S.O. post.

There're 2 options to do this:
you can implement a separate class, that will be responsible for handling NSURLConnection delegate stuff and create a separate instance for each request
you can use NSObject key-value methods on NSURLConnection instance for setting up some tag, that will be checked in connectionDidFinishLoading: method
For me, option 1 will be a better approach

Related

How to wait till asynchronous request returns data before returning value

I have send asynchronous request to a website using the following code:
NSMutableURLRequest *requestSiteToSendData = [NSMutableURLRequest requestWithURL:[[NSURL alloc]initWithString:#"www.example.com"] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
NSURLConnection *connectionToSiteToSendData = [[NSURLConnection alloc]initWithRequest:requestSiteToSendData delegate:self];
Then I used the following method defined inside NSURLConnectionDelegate to get and parse the data after the data fetching is completed.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
//parse 'data'
NSString *parsedData = [self parseDataWithData:data];
}
And then in the method in which I send the asynchronous request, I return parsedData. But the returning should only happen after the data fetching is completed and hence parsing is done. I know the question arises if that is what I need then why I am not using synchronous request. It is because I don't want my other methods to hang up when the loading is going on in background.
Quick answer : if it's asynchronous, you don't want to wait the asynchronous method.
One of the bests option would be :
The object calling wanting the data should set itself as the object that runs the asynchronous method, and in didReceiveData, you call a method such as updateData:(NSString *)parsedData, which handles the newly received data
The object calling the method should use KVO to observe any change on a property of the object that runs the asynchronous method.
Tell me if you need more informations.
Asynchronous requests run on separate thread, So we don't need to worry about handling view lockup.
If you want send a synchronous request then you have to use GCD to achieve the same. And various other details like, how much data is send/received etc. will not be available in synchronous request.
Synchronous request are helpful if your code next state is dependent on data received in response of the request.
As far as i understand you want that to return data after web call is complete. so i would suggest that create any method for webcall that returns NSData and do something like this:
NSHTTPURLResponse* urlResponse = nil;
NSError *error = [[NSError alloc] init];
NSData *responseData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&urlResponse error:&error];
if ([urlResponse statusCode] >= 200 && [urlResponse statusCode] < 300) {
// return responseData from here.
}
else {
NSLog(#"%d",[urlResponse statusCode]);
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"%#",result);
}
and you don't want to hung up your View. so call this method in background thread. like this:
[self performSelectorInBackground:#selector(WebCallMethod) withObject:nil];
Hope it Helps!!
You have this delegate method which will execute when all the downloading is completed from tha server successfully.Use this method to do the remaining process
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// do something with the data
// receivedData is declared as a method instance elsewhere
NSLog(#"Succeeded! Received %d bytes of data",[receivedData length]);
}
Ok this method gets executed when the all data is recieved.What you should do is to collect all data from -didReceiveData delegate method and then use it to parse in this method.
A must read document for you

ios - Passing on data to another method - same viewController

Please see this code as an example:
-(void)generateConnection
{
NSString *urlString = #"";
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
NSLog(#"%#", connection);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSString *partialData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[_jsonContentForText appendString:partialData];
NSLog(#"%#", partialData);
}
Really for lack knowing what it is called, but after searching - a lot - I am unable to out what this process is called.
I need to know how -(void)connection: gets the information it needs from the previous method. I don't know if this is called passing on methods to another method, but I need to create another one, so I need to know where I can learn this.
Please spare me the lines like: You need to read up on objective-c and the general stuff, because those answers do not cover the specific need I have.
I do not mind reading up on it, as long as I know what I am reading explains this. However if in any kind hearts it is easy to explain, I will not reject that offer:-)
You need to read up on Delegates and Protocols. When you create the NSURLConnection and set self as the delegate, your new NSURLConnection object is told to query self (the object that created it) to do things like find out if authentication is supported, or what to do when it receives some data. For the NSURLConnectionDelegate specifically, if your delegate implements the methods defined in NSURLConnectionDelegate Protocol, they'll be called.
Some good sources to read up on Delegates and Protocols are:
Working with Protocols(Apple)
Delegates and Data Sources(Apple)
The Basics of Protocols and Delegates(Mobile Developer Tips)

App not waiting for method to finish executing

I have a method getnamefornumbers which call a soap based web service(sudzc generated), which return a some data which i store in array to use.
But problem is that when i call the method it takes its time to execute and code after this method also executing, this result in null array.
what can i do so when this method completes its work then rest of the code executes.
You have to use custom delegates.You should define the protocol and delegate the current class to responsible for the class which performs getnamefornumbers. Once the operation done , you should return to caller class.
Here is the example of protocols http://mobiledevelopertips.com/objective-c/the-basics-of-protocols-and-delegates.html
You should use the NSURLConnection delegation methods. In an async environment that's the normal behavior:
You make a call (in an async way)
The application keeps running (after you make the 1. call the program continues with the rest of the instructions)
So you have to two solutions, make it sync, so you will only continue after an answer comes (in your case the array is filled), which I would probably disencourage. Or, you make it async, and use the array when you actually have it.
As for specifics in how to implement this, more details must be provided, in order for me to advise you.
Update 1.0
-(void)requestConnectionToServer{
NSURL *url= [NSURL URLWithString:#"myWebServiceURL"];
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:url];
self.reference=aReference;
[theRequest setHTTPMethod:#"GET"];
[theRequest setTimeoutInterval:20.0];
[NSURLConnection connectionWithRequest:theRequest delegate:self];
}
#pragma mark NSURLConnectionDelegate Implementation
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(#"Response:%#",[[NSString alloc] initWithData:webData encoding:NSASCIIStringEncoding]);
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"ERROR with theConenction %#",error);
}
Update 2.0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
myArray = [MyWebServiceAccess getnamefornumbers];
dispatch_sync(dispatch_get_main_queue(), ^{
[myArray makeSomething];
});
});

Connecting with NSURLRequest

I'm using this code:
NSString *recievedData;
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.site.com/"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
recievedData = [NSMutableData data];
NSLog(#"%#", recievedData);
} else {
// Inform the user that the connection failed.
NSLog(#"Unsuccessful.");
}
It's a modified version of this.
My problem is that it always returns
<>
Whether I'm connected to the internet or not, it always goes to successful.
You haven't received any data, you have just instantiated the object that will hold the received data. You need to implement the delegate methods for handling responses and failures and it is usually best to use NSURLConnection asynchronously.
There is some example code Using NSURLConnection
NSURLConnection doesn't work that way. You start a connection and then receive callbacks as data is received.
If you want a simple call to retrieve remote data, use NSData's dataWithContentsOfURL method. However, you should only use that on secondary threads because otherwise it will lock up your user interface for the duration of the call and the system may terminate your app if it takes too long.
See the full code at NSURLConnection example.

Objective C: Get page content

how to get a web page content from a console application or library? I mean, no UI elemens.
This is what I mean in python
from urllib import urlopen
str = urlopen("http://www.google.com").read()
or php
$str = file_get_contents('http://www.google.com');
or c#
using System.Net;
WebClient client = new WebClient();
string str = client.DownloadString( "http://www.google.com" );
Thanks
NSURLConnection is the class to use in Cocoa, it's usage is pretty straightforward...
Firstly you need to create an instance of NSURLRequest that encompasses the URL you wish to read...
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.stackoverflow.com"]
Create a NSURLConnection to handle your request...
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
Note the second parameter of the init method is a delegate. This delegate needs to implement the following set of methods...
connection:didReceiveResponse:
connection:didReceiveData:
connection:didFailWithError:
connectionDidFinishLoading:
Upon init of the NSURLConnection the download will commence. You can cancel it at any point by send the object a cancel message.
Once you have data to be read the connection will call the connection:didReceiveData: method on it's delegate passing an instance of NSData as the second parameter. This method will be called multiple times as your connection streams you data so use an instance of NSMutableData to aggregate the response...
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[mutableData appendData data];
}
Once the full contents of the URL have been read the connectionDidFinishLoading:(NSURLConnection*) method is invoked. At this point release the connection and use your data.
Check out the documentation for NSURLConnection. This is the asynchronous way to get at it. If you don't mind blocking the thread you can also check out stringWithContentsOfURL:encoding:error: on NSString.
Answer here:
objective c pulling content from website
Just remember to add the framework Webkit