NSURLConnection Object Ignoring It's Implemented Methods - ios

My question relates to the code in my single-threaded app that updates the devices' local database data via a NSURLConnection to a web service.
My NSURLConnection initialization is not going into any of it's implemented methods and it has me puzzled.
Inside my AppDelegate.m -> applicationDidFinishLaunching method, I am creating a NSURLConnection object:
//AppDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
// ... Building request URL here ...
NSString *requestURL = [NSString stringWithFormat:#"%#%#", URI,urlEncodedParamStr]
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:requestURL]];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
responseData = [[NSMutableData data] retain];
if(connection !=nil)
[connection release];
}
Execution should now proceed to any of the following appropriate NSURLConnection methods
that I implemented in AppDelegate.m:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{[responseData setLength:0];}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {[responseData appendData:data];}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{//my implementation}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {//my implementation}
But instead, execution continues, with the line directly after the init of NSURLConnection *connection, not executing any of the NSURLConnection implemented methods. I have confirmed that the request is not nil and put breakpoints in the implemented NSURLConnection methods - They are not being called.
What's going on?
Thanks as always!

You need to call
[connection start];
before the remote call will actually be started.
And even then, the next line of code will execute. It's an asynchronous call and is executed in a background thread. The response is received later and your connection... method will be called then (which can be up to the timeout (30 seconds) time later).

Related

how to send http request from non ui thread in ios

I am looking for a sample to send and receive http GET request in iOS. All I want to
do is handle communication in background thread such that it does not block main thread
and also want to handle http standard error code. Can anyone suggest me reference code or
example to handle http response data and handle proper memory management?
Any help will be thankful.
Two methods to achieve it:
1) NSURLCOnnection sendAsynchronousRequest method:
NSString *strURL= [NSString stringWithFormat:#"http://www.google.com/"];
NSURL *URL = [NSURL URLWithString:[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *requestURL = [[NSURLRequest alloc] initWithURL:URL];
[NSURLConnection sendAsynchronousRequest:requestURL
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
NSLog(#"Response is:%#",[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);
}];
2) Create and fire request then NSURLConnection Delegate Methods to get the response:
// Create the request.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.com"]];
// Create url connection and fire request
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
#pragma mark NSURLConnection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
// A response has been received, this is where we initialize the instance var you created
// so that we can append data to it in the didReceiveData method
// Furthermore, this method is called each time there is a redirect so reinitializing it
// also serves to clear it
_responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// Append the new data to the instance variable you declared
[_responseData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
// Return nil to indicate not necessary to store a cached response for this connection
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// The request is complete and data has been received
// You can parse the stuff in your instance variable now
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// The request has failed for some reason!
// Check the error var
}

NSURLConnection still store cache data

When I'm using NSURLConnection to get data from my server, iOS still cache data. When requesting new data, iOS sending a new request to my server, but the files are still stored.
I'm using NSURLRequestReloadIgnoringCacheData and returning nil in connection:willCacheResponse:.
The problem is that I'm using my own caching object, and it's kind of dum to let iOS store a duplicate.
Should I ignore this or should I delete the cache somehow?
Update
Code for creating NSURLRequest:
request = [NSURLRequest requestWithURL:[NSURL URLWithString:URLString] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0];
Code for creating NSURLConnection:
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
Code for NSURlConnectionDelegate:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
return nil;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[recivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
if (_handler) _handler(response, error, nil);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (_handler) _handler(response, nil, recivedData);
recivedData = nil;
response = nil;
}

NSURLConnection - didReceiveData didn't get called - iOS & ARC

I'm currently experimenting with the twitter streaming api and i'm trying to get a stream with NSURLConnection. As it doesn't work with twitter, i simplified everything and tried to get some source-code out of google's website, but this doesn't work neither.
The connection starts and ends, but without calling the didReceiveData delegate. I'm sure i'm missing something. Hope you guy's can help me!
In the header: #interface ViewController : UIViewController <NSURLConnectionDataDelegate, NSURLConnectionDelegate, NSURLConnectionDownloadDelegate, NSURLAuthenticationChallengeSender>
And in the body:
- (void)viewDidLoad
{
[super viewDidLoad];
NSURLConnection *connection;
NSMutableURLRequest *request;
// Do any additional setup after loading the view, typically from a nib.
request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://www.google.com"]];
[request setHTTPMethod:#"GET"];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL {
NSLog(#"Stream finished.");
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#", dataString);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"Connection failed!");
}
A couple of thoughts.
Your declaration of connectionDidFinishLoading doesn't look right. The standard NSURLConnectionDataDelegate method does not have a destinationURL parameter:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"%s", __FUNCTION__);
}
Given the presence of NSURLAuthenticationChallengeSender, if you're expecting a challenge (which you won't get with Google web site) then you'd obviously handle it accordingly:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
// For example, if you have a userid/password to use, see if this is the first
// challenge, and then tell NSURLConnection to try using those credentials, and if
// it failed a second time, you might just cancel the authentication challenge.
if (challenge.previousFailureCount == 0) {
NSURLCredential *credential = [NSURLCredential credentialWithUser:kUserID password:kPassword persistence:NSURLCredentialPersistenceForSession];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
} else {
[challenge.sender cancelAuthenticationChallenge:challenge];
}
}
By the way, you do not want to call start method when you use initWithRequest or connectionWithRequest. It's only needed if you do a simple initWithRequest:delegate:startImmediately: and instruct it to not startImmediately.
Anyway, I used the following and it works fine:
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://www.google.com"]];
[NSURLConnection connectionWithRequest:request delegate:self];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"%s", __FUNCTION__);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%s: %#", __FUNCTION__, dataString);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"%s error=%#", __FUNCTION__, error);
}
Someone said here that it was their SOAP format
NSURLConnection delegate method: didReceiveData not called ...Why ?? (iPhone SDK)
This also may be what you are looking for
NSURLConnection didReceiveData not called
Your NSURLConnection local variable connection is going out of scope at the end of viewDidLoad. Add a property to your ViewController to hold the NSURLConnection variable in scope.

NSURLConnection not calling connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:

The is my code
theDownloadConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
and it is calling these NSURLConnection delegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
But it is not calling
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten
totalBytesWritten:(NSInteger)totalBytesWritten
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
This method of NSURLConnection delegate calls when I do this
[NSURLConnection connectionWithRequest:request delegate:self];
I dont understand why this is happening?
didSendBodyData is only called when the request has a body containing message data like in POST request. You are most likely executing a GET.
From the apple docs:
connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:
Sent as the body (message data) of a request is transmitted (such as
in an http POST request).
That's because its defined in NSURLConnectionDataDelegate and you are setting NSURLConnection
delegate.

polling an external server from an app when it is launched

I am new to iOS and working on an app which runs on a real device (iPad). So, when I launch my app on the iPad after the view is visible, the app should be able poll a web server or something (without any user interaction) and get some information over HTTP and based on this information, I want fill some text fields in the app view. can you let me know if it is possible to do something like this in iOS? if so how and some sample pieces of code would be much appreciated.
Thanks.
You can download information over http using NSURLConnection in the viewWillAppear or viewDidLoad. After download the data if its XML parse using NSXMLParser (or any other XML parser for iOS).
//Lets say you have download and process method
- (void)downloadAndProcess
{
//URL you want to download Info from
NSURL* url = [NSURL URLWithString:#"http://google.com"];
//Make a mutable url request
NSMutableURLRequest* req = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:60];
NSURLConnection* conn = [NSURLConnection connectionWithRequest:req delegate:self];
if(conn)
{
//NSMutableData receivedData is an instance variable
receivedData = [[NSMutableData alloc] init];
}
}
//NSURLConnection Delegate methods here
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Error downloading data :%#",[error localizedDescription]);
// release receivedData object when connection fails
[receivedData release],receivedData = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// Connection did finish downloading data which you can process based on what your data is
// release receivedData object once you are done processing it.
[receivedData release],receivedData = nil;
}

Resources