NSURLConnection synchronous problem - objective-c

I am writing an iPhone app which will call a webservice method by using soap message format.
I need a synchronous process because table view needs those data before it can be displayed.
So I use [NSURLConnection sendSynchronousRequest:returningResponse:error:]
The problem is, the whole program will exit without any error message after the method call.
Even I put a NSLog statement just after the
[NSURLConnection sendSynchronousRequest:returningResponse:error:],
there is no any output so I am sure the program exit during that method call. Actually during
that HTTP request and response stuff.
However, if I set a breakpoint before that method call, and run the program in debug mode,
everything runs well, the program will not exit, and I got my results as well.
Can anyone figure out what is going on?
Thanks.
- (void) sendSyncHTTPRequest:(NSString *)request_data operation:(ServOperationSync *)serv_ops {
id<ServiceData> serv_data = serv_ops.dataDelegate;
NSURL *urlAddr = [NSURL URLWithString:[serv_data getServURL]];
urlRequest = [NSMutableURLRequest requestWithURL:urlAddr
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:90];
NSData *requestData = [request_data dataUsingEncoding:NSUTF8StringEncoding];
[urlRequest setValue:#"MobilePortal" forHTTPHeaderField:#"User-Agent"];
[urlRequest setValue:[serv_data getSoapAction] forHTTPHeaderField:#"SOAPAction"];
[urlRequest setValue:[NSString stringWithFormat:#"%u", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[urlRequest setValue:urlAddr.host forHTTPHeaderField:#"Host"];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:requestData];
NSLog(#"just before sending http request");
[serv_ops.responseData setData:[NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&urlResponse error:&urlError]];
NSLog(#"after sending http request");
}
Note that urlResponse and urlError are declared as instance variables.

You didn't provide us enough code to find out why your app doesn't behave correctly.
Using [NSURLConnection sendSynchronousRequest:returningResponse:error:] is generally a bad idea, because it blocks the current thread. You are probably calling it from the main thread, this will block the UI. The app won't respond to touches and feels like frozen, when the request takes long (especially on low bandwidth connection like EDGE).
The nature of networking is asynchronous. So I'd advise you to make an asynchronous request instead or use GCD. Update the Tableview in delegate methods (connection:didReceiveData: etc.). You may save the tableview data in an NSMutableArray and call [tableView reloadData] after modifying the array. The tableview would then be constructed from that array in the UITableViewDataSource delegate methods.

You need:
a run loop on your code
and don't forget your NSURLConnection
delegates

Related

NSThread is failing to load Selector method

So, I am trying to connect to a remote server to get and show data. in viewDidLoad I use an NSThread to call a function called doSomething
- (void)doSomething
{
#autoreleasepool
{
NSMutableURLRequest *httpRequest = [NSMutableURLRequest requestWithURL:someURL];
[httpRequest setHTTPMethod:#"POST"];
[httpRequest setValue:[NSString stringWithFormat:#"%d", httpRequestParametersClean.length] forHTTPHeaderField:#"Content-Length"];
[httpRequest setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[httpRequest setHTTPBody:httpRequestParametersClean];
(void)[[NSURLConnection alloc] initWithRequest:httpRequest delegate:self];
for (NSString* key in response)
{
// loop through returned values
}
}
}
The code in viewDidLoad is
[NSThread detachNewThreadSelector:#selector(someURL) toTarget:self withObject:nil];
Then I have a REFRESH button which when clicked calls doSomething as well
by simply saying [self doSomething]
My problem is that when view is loaded, the response from server comes empty. I still get no response until I click on the refresh button. Strange! What am I doing wrong?
A NSURLConnection created with initWithRequest:delegate: works asynchronously, calling the delegate functions connection:didReceiveResponse:, connection:didReceiveData:, ... later, when data is read from the server. Your code does not even start the connection, so nothing will happen anyway.
The easiest way to fix your problem is to use the synchronous version
sendSynchronousRequest:returningResponse:error:
of NSURLConnection. If doSomething is executed in a separate thread, this will not block the UI.
Added: (Thanks to #geowar for mentioning this.) Note that you can also use the delegate-based NSURLConnection methods. These are more flexible (see e.g. https://stackoverflow.com/a/15591636/1187415 for a comparison). Another good choice is sendAsynchronousRequest:queue:completionHandler:, which creates a background thread automatically.

ASIFormDataRequest: unable to send file to server using asynchronous request

I would like to send a file asynchronously to the server; however, it seems like when I do send the request to the server. The server gives me a HTTP code: 200, which is OK but no file is being uploaded to the server.
However, when I leave it to synchronous... it works perfectly. Weird..
Any ideas would be greatly appreciated,
- (void) sendCSVtoServer: ( Session * ) archive_session {
NSLog(#"file name: %#", [archive_session getFile]);
NSURL *url = [NSURL URLWithString:#"http://xx.x.xxx.xxx:3000/xxx/xxxxxxxx"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue: [archive_session getEmail] forKey:#"email"];
[request addFile: [archive_session getFile] forKey:#"csv"];
[request setDelegate:self];
[request startSynchronous];
}
Thanks!
You are setting a delegate, but you mention you did not implement any of those methods. ASIFormDataRequest extends ASIHTTPResquest, and therefore inherits all its properties.
You will have to implement methods decalred in ASIHTTPRequestDelegate, at least
- (void)requestFinished:(ASIHTTPRequest *)request;
and
- (void)requestFailed:(ASIHTTPRequest *)request;
Maybe others depending on your needs.
Your upload is probably still working (can you check your server?), but, when you send the request asynchronously, you don't have any way to determine if the request has succeeded or failed; right now you are just sedning and forgetting.
All the methods declared in ASIHTTPRequestDelegate.h are marked as optional, which is why the debugger, compiler, and runtime is not complaining.

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.

How to detect when a NSURLConnection has finished

I'm trying to use NSURLRequest and NSURLConnection to get a small bit of data (around 50 bytes) from a web API. I'm pretty sure the code below is right, but how do I actually get the received data and detect when its all downloaded?
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.com"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:req delegate:self];
By implementing NSURLConnectionDelegate, you can get the data in connection:didReceiveData: method and the connectionDidFinishLoading: method will be called when the the operation is over. Meanwhile , connection:didFailWithError: will be called if there is some error during the operation.
you set yourself as the delegate and the connection will send you calls as it goes.
example:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html
You have to use delegate's methods, read the documentation here: http://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSURLConnectionDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intf/NSURLConnectionDelegate

Wait for code to finish execution

I would like to know the easiest way to wait for code to finish execution within an objective c project because I am calling a webservice and retrieving the results and instead it is retrieving the results before the webservice has finished being called and filled.
Any suggestions please?
Btw this is my webservice code:
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:tmpURl];
[theRequest addValue:#"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[theRequest addValue:#"http://tempuri.org/GetCategory" forHTTPHeaderField:#"SOAPAction"];
NSString *msgLength=[NSString stringWithFormat:#"%i",[soapMessage length]];
[theRequest addValue:msgLength forHTTPHeaderField:#"Content-Length"];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody:[soapMessage dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *conn=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
and the code I am using to call this method from the other class:
images = [ws callWebService:api :data];
images = [ws returnArray];
now the problem is, that the second line is being executed before the first has finished
You do it easily as below,
-(void)aFunc {
Do Asynchronous A job...
while (A is not finished) {
// If A job is finished, a flag should be set. and the flag can be a exit condition of this while loop
// This executes another run loop.
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
Do things using the A's result.
}
You could use one of many of the Cocoa design patterns (Delegate, Notification, etc).
For instance you would trigger the method and wait until you receive a response back.
It looks like you are using an asynchronous request and for this case, you would need to wait until one of the delegate methods get notified that the request has finished (with error or success).
BTW, what does your request look like? Could you share some code to explain how you do the request and when and what you want to do?
Edited after the code was inserted:
You set self as the delegate of the request, and so you should be able to handle the responses.
Have a look at the NSURLConnection Class Reference. You will need to trigger your parser when the request finishes on these methos, for example:
– connection:didReceiveResponse:
– connection:didReceiveData:
– connection:didFailWithError:
Cheers,
vfn