I'm new to Objective-C and I've been working on some old code trying to dynamically check if SSL-certificate errors should be ignored or not. I have already set a NSURLConnection delegate and its methods:
@interface Downloader : NSObject <NSURLConnectionDelegate>
-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:( NSURLAuthenticationChallenge *)challenge;
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
-(void)connectionDidFinishLoading:(NSURLConnection *)connection;
Implementation:
-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
if([self.ignoreCertificateErrors isEqualToString:@"false"]){
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
CFRunLoopStop(CFRunLoopGetCurrent());
_downloadError = error;
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_downloadData appendData: data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError * error;
[_downloadData writeToFile:_downloadDest options:NSDataWritingAtomic error:&error];
}
The problem I'm facing is that -(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:( NSURLAuthenticationChallenge *)challenge is not being called before every download, so the property is not checked and the download happens regardless of the variable's value.
Does anyone know what could cause NSURLConnection to ignore its own delegate methods?
(Also, downloads happening asynchronously using NSRunLoop currentRunLoop
I know this is kind of an old issue, but non of the other answers have solved this problem for me.
This is an extract from the code that performs the asynchronous downloads:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_queue_t downloadQueue = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 );
dispatch_async(downloadQueue, ^{
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self
startImmediately:NO];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[connection start];
[ [ NSRunLoop currentRunLoop ] run ];
dispatch_semaphore_signal(semaphore);
[connection release];
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
If a delegate is never called it is very likely that your responsible object does not exist at runtime. In this case a proper made delegate implementation would check if an object to call on exists, is of expected datatype and protocol as well checking if the selector method exists. When all of those are not your issues reason it may be because of missing or wrong parameter/object was given to the delegate objects selector or never called in time.
Often the delegate is just not set after allocation (of class using a delegate) or pointing at the wrong class type or just
NULLand thats why never processed.solution: Check if your
id<DelegateProtocol>can point to an existing object at runtime and is configured to follow the correct protocol.reminder: Implementation of
Classname <ProtocolA, ProtocolB>helps you code all needed delegate methods and is publishing the method definitions in interface for you. If not - you should see any Xcode warning about it.hint: in some cases even if documentation says there are defaults you need to set a delegate. And NSURLConnection is deprecated.