i am struggling to request web service using https. I am getting this kind of error:
An error occured : The certificate for this server is invalid. You might be connecting to a server that is pretending to be “SERVER_ADDRESS” which could put your confidential information at risk.
I am not using NSUrlConnectionDelegate. Here is my method:
- (void)sendRequestWithUrl:(NSURL*)url block:(void (^)(NSDictionary *dict, NSError *error)) block{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
NSError* err = nil;
NSHTTPURLResponse* rsp = nil;
// Perform the request synchronously on this thread
NSData *rspData = [NSURLConnection sendSynchronousRequest:request returningResponse:&rsp error:&err];
if (rspData && err == nil) {
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:rspData options:NSJSONReadingMutableLeaves error:&err];
if(result) {
block(result, err);
} else {
block(nil, err);
}
}else{
DLog(#"Requesting URL: %# An error occured : %#",url,[err localizedDescription]);
block(nil, err);
}
}
How i could solve this problem ?
Apple has a technote that covers this very well:
"Technical Note TN2232: HTTPS Server Trust Evaluation"
https://developer.apple.com/library/ios/#technotes/tn2232/_index.html
Well my solution was to create class AsyncURLConnection this code i found somewhere at http://stackoverflow.com but can't find it now. So i will give the code:
AsyncURLConnection:
.h
#import <Foundation/Foundation.h>
typedef void (^completeBlock_t)(NSData *data);
typedef void (^errorBlock_t)(NSError *error);
#interface AsyncURLConnection : NSObject{
NSMutableData *data_;
completeBlock_t completeBlock_;
errorBlock_t errorBlock_;
}
+ (id)request:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock;
- (id)initWithRequest:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock;
+ (id)requestWithMutable:(NSMutableURLRequest *)request completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock;
- (id)initWithMutableRequest:(NSMutableURLRequest *)request completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock;
#end
.m
#import "AsyncURLConnection.h"
#implementation AsyncURLConnection
+ (id)requestWithMutable:(NSMutableURLRequest *)request completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock
{
return [[self alloc] initWithMutableRequest:request completeBlock:completeBlock errorBlock:errorBlock];
}
+ (id)request:(NSString*)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock
{
return [[self alloc] initWithRequest:requestUrl
completeBlock:completeBlock errorBlock:errorBlock];
}
- (id)initWithRequest:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock
{
if ((self=[super init])) {
data_ = [[NSMutableData alloc] init];
completeBlock_ = [completeBlock copy];
errorBlock_ = [errorBlock copy];
NSURL *url = [NSURL URLWithString:requestUrl];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self];
}
return self;
}
- (id)initWithMutableRequest:(NSMutableURLRequest *)request completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock
{
if ((self=[super init])) {
data_ = [[NSMutableData alloc] init];
completeBlock_ = [completeBlock copy];
errorBlock_ = [errorBlock copy];
[NSURLConnection connectionWithRequest:request delegate:self];
}
return self;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[data_ setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[data_ appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
completeBlock_(data_);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
errorBlock_(error);
}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge previousFailureCount] == 0)
{
NSURLCredential *newCredential;
newCredential=[NSURLCredential credentialWithUser:#"someUser"
password:#"someUser"
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
DLog(#"responded to authentication challenge");
}else{
DLog(#"previous authentication failure");
}
}
So in some controller this class could be used:
+ (void) downloadFileForURL:(NSURL *) url completionBlock:(void (^)(NSData *data, NSError *error)) block {
NSString *requestURL = #"https://www.google.lt/restServer/Method";
[AsyncURLConnection request:requestURL completeBlock:^(NSData *data) {
/* success! */
dispatch_queue_t downloadQueue = dispatch_queue_create("Download queue", NULL);
dispatch_async(downloadQueue, ^{
/* process downloaded data in Concurrent Queue */
if (data != nil) {
block(data, nil);
}else{
block(nil,nil);
}
dispatch_async(dispatch_get_main_queue(), ^{
/* update UI on Main Thread */
});
});
} errorBlock:^(NSError *error) {
/* error! */
block(nil,error);
}];
}
Hope some one this code could help.
Thank you all for answers.
You should add below delegate methods to your communication class.
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
if ([YOUR_HOST isEqualToString:challenge.protectionSpace.host])
{
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
}
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
This always happen for self-signed certificate. By using NSURLConnectionDelegate
- (BOOL)connection:(NSURLConnection *)connection
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
if ([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
return YES;
}
}
Trying this delegate method solved same issue for me.
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
Related
I have a custom NSURLProtocol ("UrlProtocol") written to intercept requests from a UIWebView when navigating to specific websites, and apply an extra HTTP header before being sent. I followed https://www.raywenderlich.com/59982/nsurlprotocol-tutorial for a working class. My problem comes with switching from the deprecated NSURLConnection to NSURLSession: I tested an extremely simple one-file html page, which loaded successfully. However, slightly more complex sites with resources like js files, images, etc. will timeout, whereas using NSURLConnection the entire site will load within a few seconds.
I'll paste the original UrlProtocol using NSURLConnection, then the new class using NSURLSession. The original:
#import "UrlProtocol.h"
#import "Globals.h"
#implementation UrlProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
if (![request.URL.absoluteString hasPrefix:#"http"]) return NO; //No need to intercept non-http requests
if ([NSURLProtocol propertyForKey:#"handled" inRequest:request]) {
return NO;
}
return YES;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
NSString* key = #"custom-auth-header";
Globals* globals = [Globals getInstance];
NSString* token = [globals token];
NSMutableURLRequest *newRequest = [request mutableCopy]; //Create a mutable copy that can be modified
[newRequest setValue:token forHTTPHeaderField:key];
return [newRequest copy]; //return a non-mutable copy
}
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return [super requestIsCacheEquivalent:a toRequest:b];
}
- (void)startLoading {
NSMutableURLRequest *newRequest = [self.request mutableCopy];
[NSURLProtocol setProperty:#YES forKey:#"handled" inRequest:newRequest];
self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self];
}
- (void)stopLoading {
NSLog(#"stopLoading");
[self.connection cancel];
self.connection = nil;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.client URLProtocol:self didLoadData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self.client URLProtocolDidFinishLoading:self];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self.client URLProtocol:self didFailWithError:error];
}
#end
The new UrlProtocol using NSURLSessionDataTasks for every request:
#import "UrlProtocol.h"
#import "Globals.h"
#implementation UrlProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest * _Nonnull) request {
if (![request.URL.absoluteString hasPrefix:#"http"]) return NO; //No need to intercept non-http requests
if ([NSURLProtocol propertyForKey:#"handled" inRequest:request]) {
return NO;
}
return YES;
}
+ (NSURLRequest * _Nonnull)canonicalRequestForRequest:(NSURLRequest * _Nonnull)request {
NSString* key = #"custom-auth-header";
Globals* globals = [Globals getInstance];
NSString* token = [globals token];
NSMutableURLRequest *newRequest = [request mutableCopy]; //Create a mutable copy that can be modified
[newRequest setValue:token forHTTPHeaderField:key];
return [newRequest copy]; //return a non-mutable copy
}
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest * _Nonnull)a toRequest:(NSURLRequest * _Nonnull)b {
return [super requestIsCacheEquivalent:a toRequest:b];
}
- (void)startLoading {
NSMutableURLRequest *newRequest = [self.request mutableCopy];
[NSURLProtocol setProperty:#YES forKey:#"handled" inRequest:newRequest];
[Globals setUrlSessionDelegate:self];
Globals* globals = [Globals getInstance];
self.dataTask = [globals.session dataTaskWithRequest:newRequest];
[self.dataTask resume];
}
- (void)URLSession:(NSURLSession * _Nonnull)session dataTask:(NSURLSessionDataTask * _Nullable)dataTask didReceiveData:(NSData * _Nullable)data{
[self.client URLProtocol:self didLoadData:data];
}
- (void)URLSession:(NSURLSession * _Nonnull)session dataTask:(NSURLSessionDataTask * _Nullable)dataTask didReceiveResponse:(NSURLResponse * _Nullable)response
completionHandler:(void (^ _Nullable)(NSURLSessionResponseDisposition))completionHandler{
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
completionHandler(NSURLSessionResponseAllow);
}
- (void)URLSession:(NSURLSession * _Nonnull)session task:(NSURLSessionTask * _Nonnull)task didCompleteWithError:(NSError * _Nullable)error{
if (error){
[self.client URLProtocol:self didFailWithError:error];
} else {
[self.client URLProtocolDidFinishLoading:self];
}
}
- (void)URLSession:(NSURLSession * _Nonnull)session task:(NSURLSessionTask * _Nonnull)task willPerformHTTPRedirection:(NSHTTPURLResponse * _Nonnull)response
newRequest:(NSURLRequest * _Nonnull)request completionHandler:(void (^ _Nonnull)(NSURLRequest * _Nullable))completionHandler {
completionHandler(request);
}
- (void)stopLoading {
[self.dataTask cancel];
self.dataTask = nil;
}
#end
"Globals" is a singleton where I have initialized one NSURLSession meant to be used throughout the runtime of the app. It also contains the token I set as a custom HTTP header for all requests:
#import "Globals.h"
#import "UrlProtocol.h"
#implementation Globals
#synthesize token;
#synthesize session;
static Globals *instance = nil;
+(Globals*) getInstance
{
#synchronized(self)
{
if (instance == nil)
{
instance = [Globals new];
}
}
return instance;
}
//UrlProtocol class has no init method, so the NSURLSession delegate is being set on url load. We will ensure only one NSURLSession is created.
+(void) setUrlSessionDelegate:(UrlProtocol*) urlProtocol{
Globals* globals = [Globals getInstance];
if (!globals.session){
globals.session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration delegate:urlProtocol delegateQueue:nil];
}
}
#end
Solved my problem by creating a new default NSURLSession for each NSURLSessionDataTask. Something was wrong with the way I was trying to share one NSURLSession for all my tasks. URLProtocol's startLoading method is now as follows:
- (void)startLoading {
NSMutableURLRequest *newRequest = [self.request mutableCopy];
[NSURLProtocol setProperty:#YES forKey:#"handled" inRequest:newRequest];
NSURLSessionConfiguration* config = NSURLSessionConfiguration.defaultSessionConfiguration;
NSURLSession* session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
self.dataTask = [session dataTaskWithRequest:newRequest];
[self.dataTask resume];
}
The simple HTML page test before must have worked because only one task was needed to load the page
I'm using NSURLConnection to connect to a server. It uses basic authorization. This is my code:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge previousFailureCount] == 0) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSURLCredential *newCredential = [NSURLCredential credentialWithUser:[defaults objectForKey:#"SavedUserName"]
password:[defaults objectForKey:#"SavedPassword"]
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}
else {
[self doAlert:#"Cannot acces server" omg:#"Check your login properties"];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"11111111111");
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"222222222");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"333333333333");
}
- (void)checkIfCanLogin{
[conn cancel];
conn = nil;
//setting request and so on
conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];
}
For first tries is everything ok. - I enter wrong pw, Alert is called. When I enter right password connection is loaded. But when I establish connection, I change password and after that call checkIfCanLogin again, -(void)didRecieveAuth... is not called. That means function returns that server is accessible, but it actually is not.
Any ideas how to improve my code? thanks a lot.
If you look at CredentialsController.m in Apple's AdvancedURLConnections, they illustrate how to purge credentials.
NSURLCredentialStorage *store = [NSURLCredentialStorage sharedCredentialStorage];
assert(store != nil);
for (NSURLProtectionSpace * protectionSpace in [store allCredentials]) {
NSDictionary *userToCredentialMap = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:protectionSpace];
assert(userToCredentialMap != nil);
for (NSString * user in userToCredentialMap) {
NSURLCredential *credential = [userToCredentialMap objectForKey:user];
assert(credential != nil);
[store removeCredential:credential forProtectionSpace:protectionSpace];
}
}
The Credentials.m code sample also shows how to purge credentials from the key chain.
I want to know if there is a way to connect to a secured web service (web server requests username and password to connect and return data) with a synchronous way and how can I pass these two parameters in my code, I used this code :
-(void)performRequest{
NSURL * url =[[NSURL alloc] initWithString:#"http://firstluxe.com/api/tags/?display=[id,name]&output_format=JSON"];
NSURLRequest * request = [[NSURLRequest alloc] initWithURL:url];
NSURLConnection * connection =[[NSURLConnection alloc]initWithRequest:request
delegate:self];}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{ NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if ([challenge previousFailureCount] == 0)
{
NSURLCredential * cred = [NSURLCredential credentialWithUser: #"userName"
password: #"Password"
persistence: NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:cred forAuthenticationChallenge:challenge];
}
else
{
//You don't have authentication
}
}
-(BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
{
return YES;
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
//handle errors
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
html = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
jsonFromAFNetworking = html;
NSLog(#" html is %# ",html);
}
It returns the value of from the server correctly, but when I do :
- (void)viewDidLoad {
[super viewDidLoad];
[self performRequest];
NSLog(#" jsonFromAFNetworking %#" , jsonFromAFNetworking);
}
I get null value, I know that it's because it is an asynchronous action, but I need to use the new value and I don't know how to do it, how can I tell the code to wait until the [self performRequest]is executed or how to connect to this server by another way?
I have a custom NSURLProtocol
#import <Foundation/Foundation.h>
#interface XXXURLProtocol : NSURLProtocol <NSURLSessionDataDelegate, NSURLSessionTaskDelegate>
#property (nonatomic, strong) NSURLSession *session;
#property (nonatomic, strong) NSURLSessionTask *task;
#end
#import "XXXURLProtocol.h"
#implementation DXYURLProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
if ([NSURLProtocol propertyForKey:YXURLProtocolHandled inRequest:request]) {
return NO;
}
NSString *scheme = [[request URL] scheme];
NSDictionary *dict = [request allHTTPHeaderFields];
return [dict objectForKey:#"custom_header"] == nil &&
([scheme caseInsensitiveCompare:#"http"] == NSOrderedSame ||
[scheme caseInsensitiveCompare:#"https"] == NSOrderedSame);
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a
toRequest:(NSURLRequest *)b {
return [super requestIsCacheEquivalent:a toRequest:b];
}
- (void)startLoading
{
NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
//add custom headers
[XXXURLProtocol addCustomHeaders:mutableReqeust];
[NSURLProtocol setProperty:#(YES)
forKey:YXURLProtocolHandled
inRequest:mutableReqeust];
NSURLSessionConfiguration *config;
config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.protocolClasses = #[ self ];
self.session = [NSURLSession sessionWithConfiguration:config];
self.task = [self.session dataTaskWithRequest:mutableReqeust];
[self.task resume];
}
- (void)stopLoading
{
[self.task cancel];
self.task = nil;
}
//and all other NSURLProtocolClient protocol method
#end
how to make this custom NSURLProtocol to support {upload, download}dataTask?
You have the right idea, but you need to implement some key URLSessionDelegate methods to pass the response and data up to the NSURLProtocol client:
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if( error ) {
[self.client URLProtocol:self didFailWithError:error];
} else {
[self.client URLProtocolDidFinishLoading:self];
}
}
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
completionHandler(NSURLSessionResponseAllow);
}
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
[self.client URLProtocol:self didLoadData:data];
}
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.