I can't consistently read response from a server if I use code below.
Header:
#import <Foundation/Foundation.h>
@interface TestHttpClient : NSObject<NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate>
-(void)POST:(NSString*) relativePath payLoad:(NSData*)payLoad;
@end
Implementation:
#import "TestHttpClient.h"
@implementation TestHttpClient
-(void)POST:(NSString*)relativePath payLoad:(NSData*)payLoad
{
NSURL* url = [NSURL URLWithString:@"http://apps01.ditat.net/mobile/batch"];
// Set URL credentials and save to storage
NSURLCredential *credential = [NSURLCredential credentialWithUser:@"BadUser" password:@"BadPassword" persistence: NSURLCredentialPersistencePermanent];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:[url host] port:443 protocol:[url scheme] realm:@"Ditat mobile services endpoint" authenticationMethod:NSURLAuthenticationMethodHTTPBasic];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
// Configure session
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration ephemeralSessionConfiguration];
sessionConfig.timeoutIntervalForRequest = 30.0;
sessionConfig.timeoutIntervalForResource = 60.0;
sessionConfig.HTTPMaximumConnectionsPerHost = 1;
sessionConfig.URLCredentialStorage = [NSURLCredentialStorage sharedCredentialStorage]; // Should this line be here??
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
// Create request object with parameters
NSMutableURLRequest *request =
[NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0];
// Set header data
[request setHTTPMethod:@"POST"];
[request setValue:@"application/x-protobuf" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"Version 1.0" forHTTPHeaderField:@"User-Agent"];
[request setValue:@"Demo" forHTTPHeaderField:@"AccountId"];
[request setValue:@"1234-5678" forHTTPHeaderField:@"DeviceSerialNumber"];
[request setValue:@"iOS 7.1" forHTTPHeaderField:@"OSVersion"];
[request setHTTPBody:payLoad];
// Call session to post data to server??
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
[downloadTask resume];
}
-(void)invokeDelegateWithResponse:(NSHTTPURLResponse *)response fileLocation:(NSURL*)location
{
NSLog(@"HttpClient.invokeDelegateWithResponse - code %ld", (long)[response statusCode]);
}
#pragma mark - NSURLSessionDownloadDelegate
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"NSURLSessionDownloadDelegate.didFinishDownloadingToURL");
[self invokeDelegateWithResponse:(NSHTTPURLResponse*)[downloadTask response] fileLocation:location];
[session invalidateAndCancel];
}
// Implemented as blank to avoid compiler warning
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
}
// Implemented as blank to avoid compiler warning
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
}
Can be called from any VC (place code under button action for example)
-(IBAction)buttonTouchUp:(UIButton *)sender
{
TestHttpClient *client = [[TestHttpClient alloc] init];
[client POST:@"" payLoad:nil];
return;
}
If you start program and call this code - it will show in NSLog completion with 401. Second try - will not work. Or might work if wait a little. But it won't send server requests as you push button.
NSURLSession somehow "remembers" failed attempts and won't return anything? Why is this behavior? I want to see 2 NSLog messages every time I push button.
NSURLSession
for every request. You really want to create a singleNSURLSession
and have subsequent requests use that same session. – RobdidReceiveChallenge
should probably have anelse
condition that calls thecompletionHandler
withNSURLSessionAuthChallengeCancelAuthenticationChallenge
. If thatif
statement fails, your current implementation will stall if you don't call thatcompletionHandler
at all. – Rob