The first thing I realized after starting my iPhone project last year was that most apps require some form of communication over http to interact with the outside world. And like any web application you need to understand how to send an http request and parse the response if you plan to do anything useful. I soon found I was doing web development without the html, css or javascript.
I decided to start this series because I couldn't find many 'end-to-end' examples on the web for beginners. I learned how to work with http on my own as I built and launched my first iPhone app earlier this year.
Throughout this series I'll be using a single view iPhone app for simplicity. The best place to start is with a simple GET request because we can focus on the basics required to interact with http. To make the http request and kick it off we will start coding inside the 'viewDidLoad' method of the default view controller.
First we need to supply our request with a valid url using NSURL.
After we have a valid url we can create the request itself using NSMutableURLRequest. Because this is a GET request we simply set the http method accordingly.
And finally to fire off the request we call the method 'initWithRequest' on NSURLConnection.
The entire solution put together inside the 'viewDidLoad' method now looks something like the below.
When I copy and pasted this for the first time I felt 90% of it was clear and made sense. Then I hit the last line and saw the 'delegate:self' syntax. Up to this point I hadn't done much with delegates and because of this I didn't know what would happen if I ran the code. So I did a simple build and run to find out if this worked and to my surprise it did nothing.
So after a little more reading I learned the initWithRequest method we invoked would call back to a specific class when the http response was returned with the html from http://www.google.com. In example code above we set the delegate to self (the view controller we are in currently) so if we wanted to get the html back from the server we would need to implement the method 'connectionDidFinishLoading'.
Below I added the bare method that would be invoked during this call back. Currently I only cleanup after the NSURLConnection we initialized earlier but what's missing here is that we don't have a way to get at the html that would be returned in the response.
We can't reach into the NSURLConnection directly to pull out the response data without implementing a few other delegate methods. But before we can stub out these methods we need a property to hold the data returned from the server -so in the view controllers .h file add the responseData property as follows.
Next in your .m file add the @synthesize declaration at the top and release it in your controllers dealloc method. Normal property setup but to someone new like myself it was better to see each step in detail. Also in the first line of the 'viewDidLoad' method we need to new the NSData property like so.
Now we can add the additional delegate methods required to setup and append data returned from the response. The first is called only once when the server gets the request and acknowledges it. In this 'didReceiveResponse' method we simply setup the responseData property so it will be ready to append the data sent back from the server.
And in the 'didReceiveData' method we just append the data sent back during the response.
Now we can modify our 'connectionDidFinishLoading' method to pull out the html from the responseData property. We do this by creating a string from the NSData collected during the 'didReceiveData' method invoked earlier. We wait until this method to extract the contents because it's the final step in the request + response life cycle.
In this example I used NSLog to push the string into the console for the sake of simplicity. If you now run this in Xcode using the simulator you will see the full html from http://www.google.com in the debugger console.
The only additional method I would suggest is the 'didFailWithError' because if your http request errors the call back will not invoke 'connectionDidFinishLoading' so if you need to inform the user that something unexpected has occurred you will need to do it here instead.
The full source code for this sample is available on github here.