Reading Certificates on iOS Problem - iphone

I am trying to read certificates from various URLs in iOS. My code however is not working well - the array that should return the information I need always returns null.
What am I missing?
- (void)findCertificate:(NSString *)url
{
NSInputStream*input = [[NSInputStream inputStreamWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"https://store.writeitstudios.com"]]] retain];
[input setDelegate:self];
[input scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[input open];
NSLog(#"Status: %i",[input streamStatus]);
}
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
NSLog(#"handle Event: %i",eventCode);
if (eventCode == NSStreamStatusOpen)
{
NSArray *certificates = (NSArray*)CFReadStreamCopyProperty((CFReadStreamRef)aStream, kCFStreamPropertySSLPeerCertificates);
NSLog(#"Certs: %#",CFReadStreamCopyProperty((CFReadStreamRef)aStream, kCFStreamPropertySSLPeerCertificates));
if ([certificates count] > 0) {
SecCertificateRef certificate = (SecCertificateRef)[certificates objectAtIndex:0];
NSString *description = (NSString*)SecCertificateCopySubjectSummary(certificate);
NSData *data = (NSData *)SecCertificateCopyData(certificate);
NSLog(#"Description: %#",description);
}
}
}
And yes, I am aware that I am leaking memory. This is just a snippet.

Let me explain what you're doing here and why it's wrong:
You are loading the contents of the URL https://store.writeitstudios.com (i.e. the HTML) synchronously into an NSData (a data buffer). Note that you are not loading any certificates (well, technically NSURL will load them internally, but this code is most definitely not putting them into the NSData)
You are opening an input stream and sticking the data (a bit of HTML, no certificates!) into it.
You have implemented NSStream's delegate method stream:handleEvent: and are attempting to read the kCFStreamPropertySSLPeerCertificates property. This property will be empty since the stream contains only a bit of HTML data, nothing else.
You are casting the empty property to an NSArray.
The loop is not executed because the array is NULL.
Using NSStream/CFStream is not necessary for the task at hand. And most definitely you don't have to go through NSURLConnection first and then through NSStream.
To retrieve SSL server certificates, stick to a simple, asynchronous NSURLConnection and use its delegate methods to access the certificates:
// Method to begin the asynchronous download
- (void)beginCertificateDownload:(NSURL *)url
{
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
// NSURLConnection Delegate Methods
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
// extract the certificates
SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
CFIndex count = SecTrustGetCertificateCount(trustRef);
for (CFIndex i = 0; i < count; i++) {
SecCertificateRef certRef = SecTrustGetCertificateAtIndex(trustRef, i);
CFStringRef certSummary = SecCertificateCopySubjectSummary(certRef);
NSLog(#"%#", certSummary);
// do whatever you need with the certificates here
// don't forget to copy them if you need to keep them
// around beyond the scope of this method
}
// I'm assuming you're not interested in actually loading the contents of the URL, so cancel
[[challenge sender] cancelAuthenticationChallenge:challenge];
// you'll also want to release the connection object at some point
}

Related

How to return data gotten from a web service in objective- c (iPhone)?

This might be a dumb question. Sorry if it is.
But Im working on a project that consumes web services. I can connect to the web service and get the data I need fine.
I would like to have a method that returns this data obtained from the web service to the caller. The only problem is that the data is only obtained inside the ConnectionDidFinishLoading method, and I can't access this data from my method.
here is my code, that works fine:
- (NSData *) dataForMethod:(NSString *)webMethod withPostString:(NSString *)postString
{
NSURL *url = [NSURL URLWithString:[SigameWebServiceAddress stringByAppendingFormat:#"%#%#", #"/", webMethod]];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [postString length]];
[req addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[req addValue:msgLength forHTTPHeaderField:#"Content-Length"];
[req setHTTPMethod:#"POST"];
[req setHTTPBody: [postString dataUsingEncoding:NSUTF8StringEncoding]];
conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (conn)
{
webData = [NSMutableData data];
}
// I WOULD LIKE TO RETURN WEBDATA TO THE CALLER HERE, BUT WEBDATA IS EMPTY NOW, THE
//connectionDidFinishLoading ONLY GETS CALLED WITH THE DATA I WANT AFTER THE COMPILER
//IS DONE EXECUTING MY METHOD.
}
-(void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response
{
[webData setLength: 0];
}
-(void) connection:(NSURLConnection *) connection didReceiveData:(NSData *) data
{
[webData appendData:data];
}
-(void) connection:(NSURLConnection *) connection didFailWithError:(NSError *) error
{
NSLog(#"FATAL ERROR");
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
NSLog(#"DONE. Received Bytes: %d", [webData length]);
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
//---shows the XML---
NSLog(#"%#", theXML); //NOW, THIS IS THE DATA I WANT. BUT HOW CAN I RETURN THIS TO
//THE CALLER. I MEAN, THE CALLER THAT CALLED MY METHOD
//+ (NSData *) dataForMethod: withPostString:
}
Any help here is appreciated!
Thanks
There are really two ways to go about this.
Create a delegate interface
Use Blocks
I would strongly advise against using the synchronous methods - unless you are/have created your own asynchronous framework around them (i.e. you are manually starting another thread and executing your synchronous request on that thread). In the long run you will realize you need the requests to be async, and you'll have to re-work everything such that they are.
To give a quick overview of the two options I gave:
1. Create a delegate interface
The idea here is to create a class which performs the request, and create a protocol the caller must implement. When the request is complete, you will invoke a specified method on the delegate with the data:
The protocol might look something like this:
#protocol RequestClassDelegate <NSObject>
- (void)requestCompleted:(ResponseClass *)data;
- (void)requestError:(NSError *)error;
#end
The class which makes the request might look something like this:
#interface RequestClass : NSObject
- (void)makeRequest:(id<RequestClassDelegate>)delegate;
#end
And the request class implementation might contain some of the following, in addition to your connection logic:
#implementation RequestClass
{
__weak id<RequestClassDelegate> _delegate;
}
// Connection Logic, etc.
- (void)makeRequest:(id<RequestClassDelegate>)delegate
{
_delegate = delegate;
// Initiate the request...
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
// Processing, etc.
// Here we'll call the delegate with the result:
[_delegate requestCompleted:theResult];
}
#end
2. Use Blocks
This solution is much the same as the first solution - but, a bit more elegant in my opinion. Here, we'll change the RequestClass to use blocks instead of a delegate:
typedef void (^requestCompletedBlock)(id);
typedef void (^requestErrorBlock)(NSError *);
#interface RequestClass : NSObject
#property (nonatomic, copy) requestCompletedBlock completed;
#property (nonatomic, copy) requestErrorBlock errored;
- (void)makeRequest:(requestCompletedBlock)completed error:(requestErrorBlock)error;
#end
And the implementation of that might look something like this:
#implementation RequestClass
#synthesize completed = _completed;
#synthesize errored = _errored;
// Connection Logic, etc.
- (void)makeRequest:(requestCompletedBlock)completed error:(requestErrorBlock)error
{
self.completed = completed;
self.errored = error;
// Initiate the request...
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
// Processing, etc.
// Here we'll call the delegate with the result:
self.completed(theResult);
}
#end
It sounds like you are trying to use return the data synchronously from your method, but you are using an asynchronous method (using an NSURLConnection and presumably calling its start method) to begin retrieving data. If you really want your method to return its result synchronously, read on. As #Steve says in another answer, however, you may also reconsider your interface design and instead implement it using an asynchronous approach and use his recommendations for either a delegate or block-based interface.
If you want to return the data synchronously from your method, use a synchronous request. So change this part of your code:
conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
[conn start]; // I presume you have this somewhere
if (conn)
{
webData = [NSMutableData data];
}
with something more like this:
NSURLResponse *response = nil;
NSError *error = nil;
webdata = [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&error];
if (webdata) {
return webdata;
}
else {
// Handle error by looking at response and/or error values
return nil;
}
You will no longer need any of your delegate code if you use this approach. You will be limited in some ways though. For example, if your web service requires authentication via something other than URL parameters you can't use this approach.
Steve's answer is great and I can only suggest the way using blocks. Actually, as I am new into Objective-C I implemented the approach steve outlined. It works perfectly.
The Post for more details and my own point of view you can find here:
http://kerkermeister.net/how-to-build-an-cocos2d-ios-app-communicating-with-a-restful-api-the-sequence/
The Post contains all the tiny steps you need to follow to get Steve's solution approach with blocks working. That includes:
- an updateable view that will render information as soon as retrieved from Web API asynchronously
- a controller invoking the HTTP request to the Web API
- the actual HttpRequest class that uses iOS standard NSURLConnections
- a model class that uses blocks as callbacks to update its data
Your going to have to either implement a separate method in which you use the data once the data has been returned by the connectionDidFinishLoading method or make the request synchronously. The reason I believe the above does not work is because the request is happening on a separate thread, so the main thread continues, but does not actually have the data.
This is a good way to do that if synchronous is what you want:
Does all NSURLConnections connect asynchronously? iOs
In order to download data from webserivce - use NSURLSession -
A URL session task that returns downloaded data directly to the app in memory.
// 1. create NSURL link to your webservice
NSString *dataUrl = #"DATA_LINK_TO_WEBSERVICE";
NSURL *url = [NSURL URLWithString:dataUrl];
// 2. create a NSURLSessionDataTask
NSURLSessionDataTask *downloadTask = [[NSURLSession sharedSession]
dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//Handle response here
}];
// 3.resume the task
[downloadTask resume];
Refernces:
apple documentation refrence:
https://developer.apple.com/documentation/foundation/nsurlsessiondatatask?language=objc
Raywanderlich great cookbook:
https://www.raywenderlich.com/2392-cookbook-using-nsurlsession
Your going to need to parse the XML that comes back. There are some good Objective C XML parsers out there. One in particular is made for ease of use....
http://nfarina.com/post/2843708636/a-lightweight-xml-parser-for-ios
It's a very light weight parser for extracting the values you want from XML. I've used many times with great success and little hassle. Here is how I query a web address and turn it into data.
NSString *query = [NSString stringWithFormat:#"http://WEB_ADDRESS_FOR_XML];
NSURL *URL = [NSURL URLWithString:query];
NSData *data = [NSData dataWithContentsOfURL:URL];
Or with NSURLConnection, in the did receive data:
-(void) connection:(NSURLConnection *) connection didReceiveData:(NSData *) data
{
//USE THE DATA RETURNED HERE....
}
Then use the Parser from my link to get the contents:
SMXMLDocument *document = [SMXMLDocument documentWithData:data error:NULL];
NSLog("\nXML Returned:%#",document);

iphone :client-server communication not occuring

i had made the following programming for client server programming but it is not working. the server is not able to receive the request for connection setup.plz help.
#import "clientserverprogramViewController.h"
#import "secondview.h"
#import <CoreFoundation/CFSocket.h>
#include <sys/socket.h>
#include <netinet/in.h>
NSInputStream *iStream;
NSOutputStream *oStream;
#implementation clientserverprogramViewController
#synthesize name,filepath,display;
-(IBAction) print {
NSString *urlStr = serverIP;]
[display setText : urlStr];
if (![urlStr isEqualToString:#""]) {
NSURL *website = [NSURL URLWithString:urlStr];
if (!website) {
NSLog(#"%# is not a valid URL");
return;
}
NSHost *host = [NSHost hostWithName:[website host]];
[NSStream getStreamsToHost:host port:3000 inputStream:&iStream outputStream:&oStream];
[iStream retain];
[oStream retain];
[iStream setDelegate:self];
[oStream setDelegate:self];
[iStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[oStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[iStream open];
[oStream open];
}
}
-(IBAction) settings {
[self presentModalViewController:nextview animated: YES];
}
-(IBAction) cancel {
exit(0);
}
- (void)dealloc {
[super dealloc];
}
#end
You only open streams and don't do anything with them. It's like picking up a phone and not dialing a number. Use NSStreamDelegate protocol to implement data transmission code.
Update:
You have these lines that set the delegate for streams:
[iStream setDelegate:self];
[oStream setDelegate:self];
Now implement methods that are defined in NSStreamDelegate protocol in your own class (AFAIK - there's only one of them). See how to receive/send data from there.
Is there a specific reason you're using streams?
What about using NSURLConnection? Here's a piece of code from a project of mine. Both are in KANetworkManager. KANetworkTransactionType is simply a enum that helps me know how to parse the response.
+ (void) createAndStartUrlConnection:(NSMutableURLRequest *)request type:(KANetworkTransactionType)type target:(id)target callback:(SEL)callback;
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSDictionary *requestDict = [NSDictionary dictionaryWithObjectsAndKeys:request, #"request", [NSNumber numberWithInt:type], #"type", target, #"target", [NSValue valueWithPointer:callback], #"callback", nil];
[KANetworkManager performSelectorInBackground:#selector(makeNetworkCall:) withObject:requestDict];
}
I'm able to made a synchronous network call because I always call this method on its own thread. It's a simpler way to achieve asynchronous network communications without dealing with delegates (although the delegate method provides some benefits). Your parseResponse method would need to be specific to whatever your web service it sending back. parseResponse would notify the callback method. Let me know if you have additional questions regarding this.
+ (void) makeNetworkCall:(NSDictionary *)params
{
// We assume this method won't be called from the main thread, so we need our own NSAutoreleasePool.
NSAutoreleasePool *autoreleasePool = [[NSAutoreleasePool alloc] init];
NSMutableURLRequest *request = [params objectForKey:#"request"];
KANetworkTransactionType type = [(NSNumber *)[params objectForKey:#"type"] intValue];
id target = [params objectForKey:#"target"];
SEL callback = (SEL)[[params objectForKey:#"callback"] pointerValue];
NSURLResponse *response;
NSError *err;
// We make a synchronous request assuming we're on a background thread.
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
if (data.length > 0)
{
[self parseResponse:data type:type target:target callback:callback];
}
else
{
NSLog(#"Error occured during network call. %#", err);
}
[autoreleasePool drain];
}
JB gates,
In your code you inform iStream and oStream that your clientserverprogramViewController object is to be the delegate for each. However, a proper delegate needs actual implementation. Your class needs to implement this method:
– stream:handleEvent:
The details are documented here:
Reading From Input Streams
Writing To Output Streams
Also, your code will not work on a real iPhone. There is an updated Core Foundation API for creating the socket pair, details here.
Update
Just wondering if this is not a software issue but maybe the server is behind a firewall. Please give details what the server is, ie webserver, netcat, or simple TCP socket, etc.
Peter

iphone uiwebview authentication challenge keeps firing when signed in

i have recently implemented authentication challenge log in through the iPhones UIWebView. i've got it working to the point where i get challenged then i present an alert with text fields, then send the data to the site that needs authentication.
i have not yet tried to use this on anything else besides my netgear router. But my problem is when i navigate through the settings for the router, the authentication challenge gets called, thus presenting the alert even though the user is logged in.
below is the code i'm using, any advice would be grately appreciated
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"Did start loading: %# auth:%d", [[request URL] absoluteString], _authed);
myRequest=[request copy];
if (_authed) {
NSLog(#"_authed");
_authed = NO;
// pretty sure i'm leaking here, leave me alone... i just happen to leak sometimes
[[NSURLConnection alloc] initWithRequest:request delegate:self];
return YES;
}
[[NSURLConnection alloc] initWithRequest:request delegate:self];
return YES;}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
NSLog(#"protection space %#", protectionSpace.authenticationMethod);
//if(![protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodDefault]){
return NO;
//}
//else{
// return YES;
//}
//[protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] || [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic];}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;{NSLog(#"received response via nsurlconnection %#", connection);
NSLog(#"got auth challange %#", challenge);
UIApplication* app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = NO;
/*NSString *aarrgghh=[NSString stringWithFormat:#"%#",connection];
NSString *searchForMe = #"login";
NSLog (#"arrgghhh %#",aarrgghh);
NSRange range = [aarrgghh rangeOfString:searchForMe];*/
if ([challenge previousFailureCount] <=1) {
//present alert with text fields for credentials
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
}}
-(void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
NSLog(#"Challenge cancelled");}
//`-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
NSLog(#"received data");
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;{
NSLog(#"received response via nsurlconnection %#", response);
// THIS IS WHERE YOU SET MAKE THE NEW REQUEST TO UIWebView, which will use the new saved auth info
if(_authed){
//NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:self.webView.request.URL.absoluteString]];
[webView loadRequest:myRequest];
}
}
`
Might be a simpler way to do this, but this is what worked for me.
First off, when shouldStartLoadWithRequest returns YES, that tells UIWebView to create NSURLConnections and run them for you . Since you can't assign a delegate to this connection, that's not going to work. If you want to handle authentication via a NSURLConnectionDelegate, then shouldStartLoadWithRequest should always return NO for that UIWebView.
So you need to handle the connection yourself. Fire off an NSURLConnection with the request and use the rest of the NSURLConnection delegate methods to handle the loading (e.g. keep track of the MIME type and build up an NSMutableData)
Finally, when you get to connectionDidFinishLoading, you can call UIWebView's loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName baseURL:(NSURL *)baseURL with the NSData your connection downloaded.

UrlConnection Iphone

I am trying to get data from a server using the following code.
+ (NSString *) getData:(NSString *)methodName parameters:(NSDictionary *) parameters error:(NSError **)error
{
NSString *body = [UdoziProxy getRequestBody:methodName parameters:parameters];
NSMutableURLRequest *request = [UdoziProxy createRequest:body];
// Send the request .
NSHTTPURLResponse *urlResponse = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:error];
if (responseData == nil || error !=nil) {
return nil;
}
return [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding] autorelease];
}
It works fine when the server is running but when I stop the server deliberately, the responseData object has still value and is not nil. How can I handle the situation where either the connection is lost or the server is down ?
You need to set the cache policy on your NSURLRequest object. If the synchronous API still doesn't honour that, you need to switch to using the asynchronous API and throw away the cache request object when you receive it. If that doesn't work, then maybe your network has a transparent proxy which is doing some caching for you.
you have to implement NSURLConnection delegates in
you can get failure status in
the following delegate
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
responseData =nil
}
there you have to make the recieved data to nil value
also its safe to
get data in
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{ }
which indicates that the connection is finished

iPhone NSURLConnection: connectionDidFinishLoading - how to return a string to the calling method

I have reviewed similar stackoverflow questions/answers to this but I am still stumped.
I'm a beginner and I'm really struggling with this. With the iPhone, I can download XML from a URL but I cannot store the result string in a NSString variable and see it from the calling function.
I have the following declarations in a custom made class:
#interface comms : NSObject {
NSString *currURL, *receivedString;
NSMutableData *receivedData;
NSURLConnection *conn;
}
#property (copy, readwrite) NSString *currURL;
#property (copy, readonly) NSString *receivedString;
#property (nonatomic, assign) NSMutableData *receivedData;
#property (nonatomic, assign) NSURLConnection *conn;
-(void) getContentURL;
I have the following method in the comms class:
-(void) getContentURL
{
NSLog( #"Begin getContentURL." );
// Request data related.
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init]
autorelease];
[request setURL:[NSURL URLWithString: currURL]];
// Content-Type related.
[request setValue:#"application/x-www-form-urlencoded"
forHTTPHeaderField:#"Content-Type"];
// Create Connection.
conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (conn) {
// The connection was established.
receivedData = [[NSMutableData data] retain];
NSLog( #"Data will be received from URL: %#", request.URL );
}
else
{
// The download could not be made.
NSLog( #"Data could not be received from: %#", request.URL );
}
// PROBLEM - receivedString is NULL here.
NSLog( #"From getContentURL: %#", receivedString );
}
I have created the required delegates in the comms class as per the following:
-(void)connection:(NSURLConnection *)connection didReceiveResponse:
(NSURLResponse *)response
{
// Discard all previously received data.
[receivedData setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:
(NSData *)data
{
// Append the new data to the receivedData.
[receivedData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// Connection succeeded in downloading the request.
NSLog( #"Succeeded! Received %d bytes of data", [receivedData length] );
// Convert received data into string.
receivedString = [[NSString alloc] initWithData:receivedData
encoding:NSASCIIStringEncoding];
NSLog( #"From connectionDidFinishLoading: %#", receivedString );
// release the connection, and the data object
[conn release];
[receivedData release];
}
I can successfully output the receivedString string using NSLog in the connectionDidFinishLoading delegate.
// Convert received data into string.
receivedString = [[NSString alloc] initWithData:receivedData
encoding:NSASCIIStringEncoding];
NSLog( #"From connectionDidFinishLoading: %#", receivedString );
However, when I output the receivedString string in the getContentURL it's null (and hence is also null from the ViewController.m class which I call the comms class from).
// PROBLEM - receivedString is NULL here.
NSLog( #"From getContentURL: %#", receivedString );
Any ideas on how I can see the value of receivedString in getContentURL and from the ViewController.m class?
NSURLConnection is an asynchronous API. When you start the request, the object will spawn a new thread, and only update your main one via the callback/delegate methods. Your current method will return most likely before the request is finished, and so the string of the result will not have downloaded yet!
If you want to do this synchronously, you will have two options:
Use the built in synchronous download method. Note that as this blocks, it will not allow the user to interact with the UI.
Use the C functions CFRunLoopRun() and CFRunLoopStop() to start the run loop inside your calling function, wait until the download is complete or failed, then return control back to the calling method with CFRunLoopStop().
To return data from the delegates method, please use Code Block.
See Apple's Blocks documentation.