Sunday, November 17, 2013

Create your own web service for an iOS app, part one

Follow the steps in this tutorial to learn how to create the web service backend for an iOS app called iGlobe.

In my previous TechRepublic series, we used an existing web service to create an iOS app ("Creating a web service, parts one and two"). In this series, we'll create the web service backend for a different app called iGlobe, which is a game I created a while ago.

Basically, we want the user to be able to tag a place or a person and get points for that action. (The competitor with the most points at the end of the game wins a money pot.) In order to do this, the app has to interact with a web service, which we'll create. Our web service will need to be able to:
  • Store each player's username information
  • Receive users' points
  • Present users' points
In this iOS 6/7 tutorial we'll use a helper class called SantiappsHelper, which contains the code to run these connections to the web. A standalone class in such cases is usually called a library, which takes care of those processes. If you only require one instance of such a class (like in our case), you create a Singleton pattern. You only want one instance of the connection, because you don't want many instances of the connection class creating, receiving, and disconnecting -- that could end up in multiple connections to the same resource at different times, which could confuse you or the server.

Here's what we’ll cover in this series:
1. Create the web database
2. Create the web service backend
3. Create iOS frontend (Storyboard)
4. Fetch data
  • a.  NSURLConnection
  • b.  GCD and completion blocks
5. Add the Bump API
6. Throw in social

Step 1: Create the web database

Web services are usually large databases of information; our database will need a table to store all the information we mentioned above. We interact with databases in four main ways: Create, Read, Update, and Delete (CRUD) data. So let's take a short detour and talk about databases -- specifically, their structure and how we interact with them.


Databases are information stores, which can be written as files (such as Word or PowerPoint). The information in such files has a predetermined structure that Word and PowerPoint know how to read and access in order to present what you want and let you edit it and store it again; the problem is only Word will read a docx file, and only PowerPoint will read a pptx file. The great advantages of databases are they store information in a very compact way and can be read by many different interfaces. The simpler the database, the more interfaces can read it.

We'll use a database that is usually available for free in most web hosting services. My web hosting service has phpMySQL, which comes included with a free package. If you want other databases such as MSSQL, you need a paid service. Figure A is what my database management interface looks like.
Figure A

See an enlarged view of Figure A.
We have a database named iglobe on localhost with two tables: users and tags. The users table (Figure B) contains a primary key with a username, a password, a password hint, a first and last name, as well as an email, a phone number, an address, and such regular stuff.
Figure B

See an enlarged view of Figure B.
The tags table (Figure C) also has its own primary key (tagID), the corresponding username, an identifier, the tag's latitude and longitude, the date it was created, and how many points it's worth to that user. There is also a country field, which was implemented later as the project progressed (it's been in the works since 2011).
Figure C

See an enlarged view of Figure C.

Step 2: Create the web service backend

The idea for our web service will be to read from these tables and write to them whatever data users request or post to them. This part requires you to know some PHP. Let's start by looking at what the code to read a table looks like.


First, we include the JSON.php file in order to access JSON files on your server (make sure your webserver or host provides you with at least PHP 5.2). Then, we make a connection to the database using the database user and password as well as the database host. Now we create an array object so once we execute the mysql_query where all entries from the users table are collected into $rs, we can put that object into our $arr[] object. Finally, we encode the $arr into $json and echo it onto the screen.

Once this code is up and ready along with your database (including some records), you can direct your browser to this file (which I called I get the following result:

[{"id":"35","username":"zlitsami ","password":"932d1c42a4e4880e57037994fd3584b1","password_hint":"",
","zip":"","country":"","url":"","permissions":"1","udid":"9","userCreated":"2013-01-01 14:27:22","time_queued"
:null,"time_sent":null}, {another}, {another}]
This is an array that has many elements in it. Each element is a user's table entry. Each entry is a dictionary of key value pairs. Look familiar?
Now that we know how to read information from our database, let's create the code for writing to the database.


if (!mysql_query($sql,$con))
  die('Error: ' . mysql_error());

echo "1 record added to tags";

We connect to our database again, and we create a sql statement with values to insert (these values come from a form that was either online or on a mobile device).  We execute that sql statement with our connection and echo the results for verification to the user. I called this file writephp.php.
Before we move onto iOS, let's test our service online. Create an HTML file called Writeform.html and save this code to it:

Now load the form on your web browser and submit data to your database.
I don't want to make this web service too complicated because I want to keep your attention on the iOS side, so let's create a form to eventually read points from our web service for a particular user. Create another HTML file called Testform.html and save this code to it:


And create its php counterpart:

'$username' GROUP BY username");
$resultado = array();
while($obj = mysql_fetch_object($result)) {
	$resultado[] = $obj;
Echo $json->encode($resultado);

We'll use this last bit of code later once we get more data into the database.
So far, we have a resource that returns the points for a particular user, readpoints.php; this is what's called a web service endpoint. Web services can have many endpoints. In a game or an app, we might want to get a lot of users' points at once to fill up a leader board, for example. We might want to fetch a lot of transactions from an invoice database instead of one by one. So let's get ahead of ourselves and create an endpoint to manage a set of input data. In our case, we must be able to pass the web service a set of users. Our file would look something like this:
 "ok", "code" => 0, "original request" => $post_data);
    $response = array("status" => "error", "code" => -1, "original_request" => $post_data);

$link = mysql_pconnect("localhost", "username", "password") or die("Could not connect");
mysql_select_db("iglobe") or die("Could not select database");

$arrayToReturn = array();

foreach ($post_data as $value) 
  $result = mysql_query("SELECT username, SUM(points) AS PUNTOS FROM tags WHERE username=
'$value' GROUP BY username");

  $resultado = array();
  while($obj = mysql_fetch_object($result)){
	$arrayToReturn[] = $obj;
Echo $json->encode($arrayToReturn);
This basic php code takes the passed in array as we mentioned and loops through the database to get the points for each user. This is important because we save the app a lot of trips to the web server database.

Step 3: Create iOS frontend (Storyboard)

We'll now work on our iOS Storyboard or frontend. Then we'll hardcode data and fetch web from the actual backend; this way, we can see what our frontend will require in terms of data models, and then we can fetch web data and replace our data in those data models. We'll also be learning two ways of fetching data: inline, messy code and neat and tidy coding.
Follow these steps:
  1. Create a new Empty project using Storyboards, ARC, iPhone, and NO Core Data.
  2. Go to the storyboard and drag a UITableViewController onto the grid.
  3. Create a class called UsersListViewController. In Storyboard, select the scene and in the Identity Inspector make our scene UsersListViewController type from the dropdown list.
  4. Run a quick test to make sure our tvc is working.
  5. Build & Run. You should get an empty tableview.
Let's review what we'll do in this section:
  • Add an array property to your .m file
  • Prefill that array in viewDidLoad
  • Eliminate the pesky warning lines
  • Make tableview return one section
  • Make tableview return array count
  • Make tableview cell return array objects
This should be second nature to you by now, so I'll blaze through the specifics. 
Here's the property code:
@property (nonatomic, strong) NSArray *testArray;

Here's the viewDidLoad code:

- (void)viewDidLoad
    [super viewDidLoad];

    self.testArray = [[NSArray alloc] initWithObjects:@"me", @"you", @"them", nil];
    NSLog(@"array %d", [self.testArray count]);
Here's the return array count code:

return [self.testArray count];

Here's the cFRAIP code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    // Configure the cell...
    cell.textLabel.text = [self.testArray objectAtIndex:indexPath.row];
    return cell;
Before you Build & Run, select the UITableViewCell in Storyboard and, in the Attributes Inspector, make sure you use Cell as the Reuse Identifier. Your app should work fine.
If you Build & Run now, users should be displayed in the tableview. Cool!  That's what we're going to want to do -- that is, display a list of users in a tableview and then add in the points, like a score table.
Figure D is a mockup of what our app will look like. In essence, we'll have a tab bar controller manage three views: Users, Map, and Instructions. We'll also throw in a Login view as the app launches. This should give you an idea of what kinds of tasks we'll need to perform in order to accomplish this.
a)  Present a login view controller
b)  Save user and pass information
c)  Fetch user data from the web service
d)  Plot points on a map
e)  Display instructions in a view
Figure D

See an enlarged view of Figure D.
You should be able to re-create this in your Storyboard. Here are the basic steps:

1. Select your existing UsersViewController scene and, from the Editor menu, select Embed In | Tab Bar Controller. You should have a scene and a class for UsersViewController, and the scene should be set to its Class Type in the Identity Inspector. 

2. Clear out the second scene that was added when you embedded your tableview scene in a tab bar (by clear out, I mean make sure it doesn’t have any labels or other controls in it). Now drag a UIMapView into it. Add a UINavigationBar to the top and two buttons (Plot and Bump) on either side. Create a MapViewController class for it and set its type. Add a MKMapView IBOutlet property and two UIBarButtonItem IBOutlet properties and connect them. Add the MKMapViewDelegate.

3. For the last view add another UIViewController and drag a UIWebView and a UINavigationBar into it. Create its class file and name it InstructionsVC. Add a UIWebView IBOutlet property and connect it. Add the UIWebViewDelegate and don’t forget to set its scene type. 

4. Add a UIViewController, call it ModalViewController (Figure E is what mine looks like), and create all of the IBOutlet properties for it -- that's four labels with static text (User, Pass, Email, and Pass Requires…). There are three UITextFields with placeholder text to guide the user. There are three UIButtons for different actions. The person icon is a button with a Background Image set to the image; it will be the button the users will use to upload their image to the web server.

Other class files we could create now are TagListController, Tag/Users Model, and Annotation/PlacemarkVC.
Figure E

See an enlarged view of Figure E.
Take a couple of minutes to visualize what the app layout will look like now that we have a better idea of where we're headed, and then compare your visualization to the initial sketch you made of your app.

In part two, we'll connect to the web service and fetch actual data.