In my class I create a CBUrlConnection:
urlConnection = [NSURLConnection connectionWithRequest:request delegate:self];
[urlConnection start];
but I don't get any response, these delegate methods are never invoked:
- (void)connection:(NSURLConnection *)connection didFinishLoadingData:(NSData *)data error:(NSError *)error
- (void)connection:(NSURLConnection *)connection didUpdateProgress:(CGFloat)percent
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
The request seems to be correct, the server url is surely correct, and the server is working correctly. What could be wrong ?
I've just fixed it... it was because the code wasn't running on the main thread.
For who might be interested I've solved with:
dispatch_sync(dispatch_get_main_queue(), ^{
});
You can absolutely run an NSURLConnection from inside an NSOperation.
The actual trick is that an NSURLConnection needs a run loop. See http://www.cocoaintheshell.com/2011/04/nsurlconnection-synchronous-asynchronous/ and https://stackoverflow.com/a/6238764/171933
Johannes
Related
I have to solve the problem that NSURLConnection automatically redirects POST redirects with a 302 response as GET requests (and drops the HTTP body and some headers).
I found and successfully tried the NSURLConnectionDataDelegate solution (e.g. here), implementing:
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
and throwing away/fixing the problematic request. This works.
However. As I understand it, this means I have to use the delegate APIs like:
[NSURLConnection connectionWithRequest:request delegate:self];
Is there a way to fix the redirect using the much more comfortable block-based asynchronous API as well?:
+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
I'm currently using NSURLConnection to test if I can successfully connect to a server. Up until now, everything has worked flawlessly. The delegate methods get called, I can do what i want. But when I want to set a BOOL called connected in.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.connected = YES;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
self.connected = NO;
}
I always get NO.
I'm using my connection class in another class. I access my variable by doing this.
Connection *connection = [[Connection alloc] init];
[connection connectTo:#"localhost"];
connection.connected;<------ this is always NO.
Thanks
Your connectTo method is being called asynchronously. Meaning, after calling connectTo, the execution will proceed immediately to the next line where you check for your connected property. It won't wait for the connection to receive a response.
Also, you may want to take a look at Apple's Reachability class, which is provided for exactly this sort of connection testing:
http://developer.apple.com/library/ios/#samplecode/Reachability
I want to retrieve the username of the member who publish something in Facebook with my iPhone App.
I got it but in bad format.
My code :
//My method
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
NSLog(#"received response %#",response);
//The callback
[_facebook requestWithGraphPath:#"https://graph.facebook.com/me" andDelegate:self];
And i got this in GDB:
received response <NSHTTPURLResponse: 0x1a11e0>
What's the format : JSON i think but how can i transform it in a simple NSString ?
Thanks
Flo.
You are using the wrong method to access the response. You are using a method from the NSURLConnection delegate protocol.
You should implement the following methods as well:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
This method can be called many times, so you'd like to add the incoming data to a NSMutableData instance.
and
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
which will tell you that loading of the data has finished, your response is complete.
When the received data is complete you can create a string with it with.
- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
I'd recommend a JSON Framework to parse json strings.
You can try with JSON-Framework for parsing JSON.
Anyway... you should look at the NSURLResponse Class Reference...
Hey all, I'm trying to use Yahoo's PlaceFinder to do reverse geocoding for an app I'm making. Problem is I need to use the NSURLConnection to call to my database. So I decided to make a custom class that is initialized with the user's latitude and longitude, and only store a string variable containing the state the user is in.
Update the following code now works fine....
Here is the .h
#import <Foundation/Foundation.h>
#import "CJSONDeserializer.h"
#interface StateFinder : NSObject
{
NSString *userState;
NSURLConnection *connection;
}
-(id)initwithLatitude:(NSString *)latitude andLongitude:(NSString *)longitude;
#property (nonatomic, retain) NSString *userState;
#property (nonatomic, retain) NSURLConnection *connection;
#end
and the .m
#import "StateFinder.h"
#implementation StateFinder
#synthesize userState;
#synthesize connection;
-(id)initwithLatitude:(NSString *)latitude andLongitude:(NSString *)longitude
{
if(self = [super init])
{
NSString *lat = latitude;
NSString *lon = longitude;
NSString *stateURLFinder = [NSString stringWithFormat:#"http://where.yahooapis.com/geocode?q=%#,+%#&gflags=R&flags=J&appid=zqoGxo7k", lat, lon];
//NSLog(stateURLFinder);
NSURL *stateURL = [NSURL URLWithString:stateURLFinder];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: stateURL];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[request release];
}
return self;
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"didReceiveResponse");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"didFinishLoading");
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError");
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Store incoming data into a string
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(jsonString);
// Yes, this is incomplete, but I was waiting for the method to fire before going
// any further. This will at least show me the JSON data being returned from yahoo
// in string format so I can output it to the console via NSLog
}
- (void)dealloc
{
[userState release];
[connection release];
[super dealloc];
}
#end
This is the current code I'm using and it works fine. All I did was include the connectionDidFinishLoading and didFailWithError methods to the original code. With regards to the connection being released before it was made, I used the code above as is without the previously mentioned methods and neither didReceiveData/didReceiveResponse would hit. It wasn't until those 2 methods were included that the methods began getting called. Not sure how, not sure why, but that was the only change among all of those suggested that worked. Big thanks to #Jiva DeVoe , #XJones , #jlehr and #Aby for all the tips/hints/suggestions!
Actually, I advise that you definitely do not use sendSynchronousRequest. You should always try to use asynchronous networking unless the app you're developing is a command line app without a run loop.
I suspect your problem may be that you're releasing the connection immediately, so it's never getting a chance to run. You should add a member variable and keep it around until you've received a response or whatever.
Bonus tip:
Guessing you're probably doing this for either iOS or the Mac, and writing GUI apps. These apps have run loops. When you use synchronous networking like the prior answer suggests, you prevent that runloop from executing. This means that if the request takes longer than a few seconds, your iOS app will be killed by the OS, and your Mac app will appear non-responsive. Neither of these are good results.
You're sending a release message to the connection before it's had a chance to run; don't do that. With regards to JSON, the string you said was returned from the server is JSON. Were you expecting something else?
Get rid of the line:
[connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
Once you've initialized the connection with the request it runs automatically. You have other problems as well. Your implementation of the NSURLConnectionDelegate protocol is wrong. You need to incrementally add data received in connection:didReceiveResponse to an NSMutableData object. You can convert it to JSON in `connectionDidFinishLoading:'.
As for the memory leak, release the connection in connectionDidFinishLoading: or connection:didFailWithError: You are guaranteed to receive one but not both of them.
Everything you need to know is here
[EDIT: added NSURLConnection code sample]
// Attach this to the touchUpInside event of a UIButton
// Note that all objects will be autoreleased
// Note that you can comment out any or all of the NSURLConnection delegate methods
// and the request will execute
- (IBAction)initiateRequest
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL urlWithString:#"http://www.google.com"]];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didRecieveData:(NSData *)date
{
NSLog(#"connection:didReceiveData");
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"connection:didReceiveResponse:");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"connectionDidFinishLoading:");
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"connection:didFailWithError:");
}
Thanks to XJones for the suggestion. I wasn't including the two methods didFinishLoading or didFailWithError once inserted into my code, both didReceiveResponse and didReceiveData both began to hit. Thank you all for the tips, advice and suggestions and hopefully this helps someone else out down the road.
The code for this question is too long to be of any use. But I'm pretty sure my problem has to do with releasing a class.
I have a helper class, ConnectionHelper.h/.m, that handles a NSURLConnection for me. Basically, I give it the URL I want and it returns the data (it happens to do a quick json parse on it too). It has a delegate which I set to the calling class (in this case: DownloadViewController). When it finishes the download, it calls [delegate didFinishParseOf:objectName withDictionary:dictionary];. Then in DownloadViewController I release ConnectionHelper and alloc a new one in order to download the next object.
My problem is, I do this once, and then it creates the connection for the second one, and then my program just crashes. After this call:
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyNever];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
Then I don't think any of the following methods are called:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
So am I right in that I'm not releasing something? When I release it the first time, the dealloc function isn't being called. Is there a way I can "force" it to deallocate? Do I need to force it to? I didn't think it would matter since I allocating a new ConnectionHelper for the new call. How else would they overlap / conflict with each other?
Thank you.
First of all you never force deallocate. If you follow the memory management rules closely then you shouldn't even have to worry about it. For the rules Look at:
http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447-SW1
If your app is crashing it sounds to me more like something is being released early. Probably the object which you are setting as the delegate for your connection. Last but not least have you looked at ASIHTTPRequest for handling connections? It's a CFNetwork wrapper, very simple to use and very powerful.
Hopes this helps.