iOS tutorial, part 2: Creating a web service

Learn how to roll your own web service and interact with it in an iOS environment. We use a weather app for the sample data.

Before jumping into creating a web service, let's modify the Flickr-based API calls from our previous project to look
into another web service. We'll explore a more complex response, which will set us up for the meat of this tutorial: creating
our own web service and interacting with it.

The basics remain the same throughout most web
services. For this example, I chose a weather service from World Weather Online and used the free API (there is also a paid service). After you log in to your account, go to the API Explorer. Select the Free Weather API from the dropdown menu and click Get Local Weather (Figure A).

Figure A

When you click the Get button to the left of Local Weather,
it expands to show the options your Get HTTP request can
have. Leave the values as-is and
click the Try it! button at the bottom. You should get what you see in Figure B.

Figure B

This is basically telling us what the API request should be — that is, the Request Uniform Resource Identifier (URI). Copy that link and paste it
into a browser window. You should get a bunch of text that starts like this:

{ "data": { "current_condition"

This is returning a JSON dictionary, which you
must now parse. Let's take
this URI and put it into our previous Flickr app where the Flickr URL used to
be. Your code will look like this:

Run your app. It will crash, because we're still trying to parse our new data
with our old schema or structure. If you had an NSLog for your flickrDictionary in your
connection:didReceiveResponse method, add a breakpoint to that line or just
after it — this will stop the
program execution at that line and let you see the NSLog before the app
crashes. (Breakpoints must be
activated for the execution to stop at each breakpoint.) You can also let it crash and
look in the console; the received
response will still be logged there.

The idea is to see what the new response dictionary looks
like in order to restructure our tableview methods to handle the new
schema. If you look at the
line that logs the string, it looks like unreadable code; however, if you log the dictionary, you can see the structure in a clearer way. The new schema looks something like
this:

1) data

a. current condition

i. a
bunch of parameters such as cloudcover

b. request

c. weather

i. date
for 5 days since that's the value we chose

Now comes some thought processing that will cause you to rack your brain. We have a data dictionary with three entries. We want data from
the first entry called "current_condition" — specifically, we want its "weatherDesc" key, so "data.current_condition.weatherDesc" is the branch we wish to reach. My way of doing it will introduce you to a method
called isKindOfClass.

We know our
flickrDictionary is an NSDictionary because I told you to use that
object, but let's really test
it. Add these lines below your
NSLog flickrDictionary line:

Run your app and check the console for that text. A quick and easy way to do it,
especially when you have lots of things logging in the console, is to use your console's Find feature. After the app crashes or stops at the breakpoint, click inside the console to make sure the Find search bar opens for it and not for the editor window on top; then, click Cmd+F to open the search bar on the top right. Copy and paste the text.

So you know it's a dictionary — big whoop, right? If flickrDictionary is a dictionary, it
must contain entries. One entry you see at the beginning is "data" so let's get that key's object and log it. Replace
your //test code block with this:

We took the dictionary's data entry (which we
could see in the console) and put it into an id type object; this means it's an object of unknown
type. Then, we test if that object
is a dictionary. Run the app and
find the logged text. Let's
look for the next entry, "current_condition":

Run it again. You couldn't find the "OMG!" text, could
you? That's because that next
object is not a dictionary. Replace the NSDictionary class for NSArray class in that last if test
and check the console again. This is a handy way of testing for unknown
objects. Web services are
notorious for returning JSON strings, which are not very human readable. Remember: It's always good to
test.

Now we have an array
inside the "current_condition" entry. One way to tell them apart is that dictionaries start with a "{" curly
brace whereas arrays start with a "(" or "[". So this object inside "current_condition" is an array, which
has objects at certain indices instead of values or objects for keys. To get our first object from that
array, we will do this:

Run it and find your text. Now we're starting to get a feel for what a meaty
server response looks like.

We would like to get the value for weatherDesc,
which is an entry inside this new dictionary. But weatherDesc's value is another array with a dictionary at
its index:0, which itself has a dictionary consisting of only one entry called "value". That's the one we
want, and this is how we get it:

Now we have the value for today's (current condition) weather: "Clear". (It would have been a lot
easier to just open the window, wouldn't it?) Let's create a mutable array to put the "Clear" value into
it. If you're using the old project as a starting point, you'll have an NSMutableArray called cFRAIPArray
already in there as an ivar. Let's take our "Clear" value and put it inside:

Let's get the forecasts for the next five days. If you look at the logged flickrDictionary in the console, you'll see that at the same hierarchical level as current_condition, you have
a dictionary called "weather"; its
contents reside in an array with many objects, each corresponding to a
different day. So translated to
code, the next value we would need is called:

Run and find tomorrow in the console. Now we can add this to the our
cFRAIPArray and get the next three days. Remember our URI called for 5 days and day 1 is current_condition, so our complete method would look like this:

We can do this because we have all of our array loading code
in the connection:didReceiveData. As this loads and finally reaches the connectionDidFinishLoading, the
tableview's reloadData method is called to refresh the view with the finalized
data.

By Marcio Valenzuela

My name is Marcio Valenzuela and I am from Honduras. I have been coding in iOS for 5 years and I previously worked on web applications in ASP and PHP/mySQL. I have a few apps up in the app store and am currently working on a couple of Cocos2d games...

Full Bio

My name is Marcio Valenzuela and I am from Honduras. I have been coding in iOS for 5 years and I previously worked on web applications in ASP and PHP/mySQL. I have a few apps up in the app store and am currently working on a couple of Cocos2d games at Santiapps.com. I have a BS in Biochemistry, Masters in Business Administration and yet being a father has me stumped :). I've lived in Tampa, Paul Smith, D.C., Savannah and currently San Pedro Sula. I've visited Canada, France, Spain, U.K., China, Hong Kong and Mexico. As you can see I love cultural diversity as well as learning about a wide variety of subjects.