Monday, July 18, 2011

Simple Core Data Tutorial

This is our long overdue Core Data Tutorial. We are going to create an app similar to our SQLite3 tutorial. Where we store the NBA player's name and nickname (well in SQLite3 tutorial it was name and team) in a Core Data storage.

Quick guide about Core Data- it provides an abstraction from our persistent store, which for most of the time is still going to be SQLite3. But instead of manually writing SQL statements and accessing SQLite3's C API, we are going to do our saving and fetching all in objective C.

In Core Data, a table is an entity description and a table field is an attribute of that entity. In runtime an entity becomes an NSManagedObject or a subclass of it. It sounds complicated I know, but its not as hard as you think.

We also need an NSManagedObjectContext which we get from our app delegate. We get this free when we check the use core data storage checkbox when we create a new project. Now the managed object context is a scratch pad that monitors changes to our object and it is the one in charge of executing saves and retrievals. For instance, it makes sure that we don't have an object that is only partially saved.

So lets get started!

This is how our final app will look like:


The first view lets you create a player name and player nickname. After you press save it pushes to a table view that lists all the players that were saved in our core data.

So open xcode > create new project >window-based application with core data sa storage checked > name it players_SG.

First lets create our data model in Core Data. Right under your resources folder, you will see players_SG.xcdatamodeld. Click that and you will see players_SG.xcdatamodel. This is what we need. Double click to open it in our model editor.


Create an entity by clicking the plus (+) button near area (1). Then change the name (3) to Player. We'd like to capitalize the first letter of the entity name and small caps for our attribute name later. Notice that the class is NSManagedObject, that is because at run time, our data becomes an NSManagedObject. If you wish we can also subclass NSManagedObject. But we won't be doing that in this simple tutorial.

Then create an attribute by clicking plus (+) at area (2) select add attribute. At area (3):

Make the attribute Name: name.
Leave the optional checked. This means that the value of name can be nil. Transient means attributes are used to store non standard objects for which there is no pre-defined type. Now, change the type to String. At runtime this becomes NSString. Well, obviously right. I told you its not that difficult. You can also specify min max length, reg ex and default value. But we don't want to limit our user from creating the name of a certain player so lets keep it a simple string.

Next make another attribute named: nickname. Also optional and String. Now save our data. 

Lets move to code. Go to resources folder, right click add> new file> UIViewController subclass, with nib. Save as addViewController.

Edit addPlayerViewController.h.
We add two outlets for our nib. And a method to save our data to core data.

Now at the implementation file. Synthesize our outlets.

After @implementation addPlayerViewController

type:
synthesize nameTextField, nicknameTextField;

at the dealloc 
type:
[nameTextField release];
[nicknameTextField release];

Press command-B to build the project without running it. We need it to connect our outlets to our UI in Interface Builder.

Double click addPlayerViewController.xib. Edit it at IB to look like this.

Connect your textfields to the approprite outlets. Control-click from file's owner to the top textfield, select name. Do the same for the second textfield, select nickname this time. Select the top textfield and press command 1 to toggle the attributes inspector. At placeholder: type name. So the label "name" appears as a light gray label inside our textfield. It saves us having to drag a label on top of our textfield to mark it as the "name" textfield. Plus, I think its better UI. Now, do the same for our next textfield, this time change the placeholder text to "nickname".

Control -s to save the nib, now go back to xcode.

In our viewDidLoad, we just create a save button in our navigation controller on the upper right corner of the screen. This button calls the method savePlayer when pushed. So we implemented in our -(void)savePlayer.

First we create na instance of ListViewController. Which is the table view for the players. Sorry for including this here, we will create it a little later don't worry.

For our core data to work, we first need to get our managed object context from our appdelegate's property.

Then we create an NSManagedObjectContext using the NSEntityDescription insertNewObjectForEntityForName. We name it Player because as you remember in our data modeler, our entity's name is Player. Next we populate our entity by calling setValue: forKey: in our NSManagedObject. In a way this is quite similar to NSDictionary right? Here we just set the value of our name attribute to whatever the user types in the nameTextField. And our player's nickname to whatever the user types in our nickname textfield. Easy right?

Now to save it we need to declare an NSError object just in case we need it when the save is unsuccessful. As you remember, I said it is the NSManagedObjectContext's job to save. So the call [context save:&error]; saves our data to our model. We can also create an if statement to log errors in case this fails.

The next line just pushes the table view with all the saved records. So lets do that now...

Go to classes folder, right click select add new file>UIViewController> check subclass of UITableView Controller, no nib for this. Name it ListOfPlayersViewController.

Edit the interface file:

First thing we do is to make our class conform to the NSFetchedResultsControllerDelegate. This makes it easier for us to display our managed objects from core data to a table view. It also gives us a lot of functionality for free like sections, and gives us the ability to edit and delete entries in core data by deleting rows in our table view. Cool huh? 

In our instance variable, we declare an NSFetchedResultsController object and our NSManagedObjectContext. Then we make our NSFetchedResultsController as a property so that we can have getters and setters for it.

Now head on to our impelementation file.


In our viewDidLoad, we just created an edit button on the right side of our navigation controller. Also typed in our title.

Now the next method is the getter method for our fetchedResultsController, as I said we need this so our table view can conviniently display our core data entries.

First we check if we already created our instance of fetchedResultsController. We lazily instantiate if not.  

To create our fetchedRequestController we first need to get to our context, again its from our app delegate. Then we create an NSFetchRequest. This is like a SQL statement for requesting objects from our tables. We create a fetch request by passing it an NSEntityDescription, like what table do we want our DB to query, if this were SQL. It also lets us narrow a search by giving us a chance to pass it an NSPredicate. Though we won't do that here, because we want all our data presented. Also, it gives us a fetch batch size, in case you have gazillions of data in your persistence store, your iphone won't fetch all of them at the same time, only the batch size.

Next we pass an array of sort descriptor. Its an array because it will sort first by using the first sort descriptor and moves on the next. Kinda like sorting the lastnames first before sorting the firstname.

Then after we have our fetch request object. We can create an NSFetchedResultsController and then pass our fetch request object to it. The section name key path is just which attribute or relationship is used to make the sections in our table view.

Then we declare the self as the NSFetchedResultsController delegate. That means we have to implement its methods.

Then we let it performFetch. Which is the actual command to fetch our records from core data.


These methods are responsible for coordinating the core data entries with the table view entries. So if you for example delete a cell from table view, it also deletes the same one from core data. 

For more details on this methods, head on over to apple's documentations, where I literally copy pasted these methods. :)

Lets go hook our table view methods to our NSFetchedResultsController:

Again I grabbed this from apple's documentation. It just makes sure to display the correct number of sections, correct number of rows in the section, correct title of the section's header,and  the correct cell to display in a given row. It also has the method for editing the table view, in this case the deletion of a cell.

Pay attention to cellForRowAtIndexPath: method. Here, we get our NSManagedObject Player from our NSFetchedResultsController. Then we extract our name and nickname from the player using the valueForKey: method. Then we display it to our table view.

Now, our table view is synced with our core data, using the NSFetchedResultsController. It also gives us free functionality like, deleting rows and displaying sections in our table view. Not too bad eh?

Build and run! Enjoy!

Sunday, July 3, 2011

Simple SQLite Tutorial

We are going to create a simple app that gets data from an SQLite database. We will be using SQLite's C API to do this. As I said, this tutorial will keep things simple. Our app will just be displaying data, it won't be inserting data in the database, at least not yet in this tutorial.






So let's get started.


SQLite is a lightweight database that is embedded in the iPhone. And, it is already present in our macs, and we can easily use it through the terminal. All we need is a few SQL know how.


Open terminal.


Type this command: sqlite3 players.sql


This runs sqlite3 and creates a database named players.sql.


Now lets create a table named player that has 3 columns, id, name and team. Id is an integer that uniquely identifies the player entry, this is our primary key. The name would be the name of an NBA player and the Team would be the team name he plays for.

Type: CREATE TABLE player (id INTEGER PRIMARY KEY, name VARCHAR, team VARCHAR);


Note: Don't forget the semicolon. SQL statements should have them at the end.
This creates our player table with the corresponding 3 columns I mentioned.


So, its time to put entries into our database table.


Type: INSERT INTO player (name, team) VALUES ('Lebron James', 'Miami Heat');
This adds an entry with name of 'Lebron James' and team 'Miami Heat'.


Add more entries to our table:
What we are doing here is just adding more rows to our table, go ahead and add some more if you like.
After this open xcdoe > start new project > window based application. Name it players.

First thing we do when we use SQLite3 in our project is to add both our database in our resources folder and add the SQLite framework. 

Copy players.sql from the folder you saved it into. I happened to save mine at the Desktop, as seen from the picture above. Copy it into your resources folder, check "Copy items into destination's folder". (I added my database this way, but I actually , as did a lot of other people in some coding forums, had problems, because the database that was added was empty. I will discuss the remedy to this later).

After copying our database file lets add our sqlite3 framework. Go to our frameworks folder, right click >add > existing frameworks...>libsqlite3.0.dylib.

Now lets go to our code. Edit playersViewController.h:
Here, we import sqlite3.h. Declare an sqlite3 object that will be our database handle. We also declare 2 other ivars: an NSMutableDictionary, which we will use to hold a row of players data. The keys of the dictionary would be name and team, and the values would be the player's name and his team. This dictionary would then be stored in an array. Such that every object in the array would correspond to one row in the database. We would need these ivars to populate our table view later on.

And oh, dont forget to make playersViewController a subclass of UITableViewController.

Also, declare a conveniece method - (void)loadDatabase;

Now lets go to our playersViewController.m:

Here we implement the first part of our convenience method. First we get the path to the players.sql we added earlier to our file. We do this by using the NSSearchPathForDirectories function. The first argument means we are looking for our Documents folder. Here are the other Directories in there:
Now, the function would return to us an Array, but it only has one object in it. So we grab that object using objectAtIndex:0, which returns us an NSString. Then we append the path component players.sql so we have the full directory path to players.sql.  

Then we use the next lines of code to see whether our players.sql is exactly in our directory by using
[fileManager fileExistsAtPath:databaseDirectory]. We log our result in the console, with the exact directory of the database. We do this so we can remedy the problem with potentially adding an empty database file. In my experience my players.sql was added to the directory address but it was empty, it didnt have the player table nor the columns and the data I inserted into it. So as a remedy, using finder, navigate to the directory path logged in the console and copy paste our players.sql into that folder. This guarantees that we added a players.sql that is not empty.


Now, lets continue to our loadDatabase method:

First we open our database, using sqlite3_open(). First argument is the databaseDirectory we created earlier, we convert it to a C string using UTF8String. Second argument is our database handle. The  if just checks whether or not we opened the database successfully. If we failed we just close our database (standard procedure accdg. to SQLite docs) and log our error message.

After successfully opening the database, we declare our SQL statement, which will retreive all entries from our table. Next we declare sqlite3_stmt object which is an SQLite3 binary compiled statement.

Next we compile our SQL statement into a byte-code program (our sqlite3_stmt) using sqlite3_prepare_v2.

The first argument is a database connection obtained from a prior successful call to sqlite3_open(). The second argument is the statement to be compiled, encoded as UTF-8. The third argument is the maximum length of sql statement in bytes, when we pass a number less than zero, then sql is read up to the first zero terminator. Next argument is our statement handle, our sqlite3_stmt object. Last argument is the pointer to unused portion of Sql, but since it is read up to the first zero terminator, we will pass in NULL.

After a prepared statement has been prepared using either sqlite3_prepare_v2,  the sqlite3_step() function must be called one or more times to evaluate the statement. If the function returns SQLITE_ROW means that there is another row of data ready.

We then get that row of data, by using the sqlite3_column_text(), where we pass our compiled statement and the column number we want to access. First column is 0 second is 1, much like an array. Our name column is the second column in our table so we use 1. Similarly, team is the third, so in the next line we use 2.

This function returns a C string, so we turn it to NSString using stringWithUTF8String method. Then we store the playerName and playerTeam strings in our dictPlayers dictionary, which holds the data for an entire row. We then add an entire row's data to our arrayPlayers. Which holds all the rows of data from the database. Easy right? We then release the dictPlayers, so that when the while loop starts again for the next row, we will start with a blank dictPlayers dictionary.

We then finalize our statement after stepping thru all our rows to release the resources we used in compiling it.

Now, we have effectively retreived our data from an SQLite database and turned them into objective c objects (our NSMutableArray of NSMutableDictionaries of NSStrings).

Lastly, lets do some basic table view stuff, so our data shows up in a table view.


First we implement the tableView:numberOfRowsInSection: method and give it the number of objects in our arrayPlayers. Then we implement tableView:cellForRowAtIndexPath:, where we get a particular player's data from our arrayPlayer. We then put it in aPlayer. Then we extract the object for key @"name" and @"team", which we set as our cell's textLabel and detailTextLabel respectively. That should take care of our table view. 

Now, its time to add our table view to our view. Go to playersAppDelegate.m:

Thats all there is to it. Build and Run. You should see the name and the team of our players in the table view! Yey! 

For questions and suggestions hit the comments. Thanks!








Friday, June 24, 2011

Adding Icons to our movies and flickr App









If you followed our movies app and flickr app tutorials, and feel that there is something lacking. There is, we dont have an icon. So lets add them.

Download the files here.
movies icons
flickrer icons (the flickr app)
zneaker icons (the simple tab bar app)

There are two png files. One for retina display, and one for non hd. Just add the unzipped pngs to the resources folder and check "copy items into destination group's folder". Notice that the names are icon.png and icon@2x.png. Well, if you want to send your app to the app store someday, you would want to stick to this naming convention. The icon.png is non-hd and the @2x is the retina display version. Well, once you've copied it your done! Enjoy our new icons.

Tuesday, June 21, 2011

Creating a REST Web Service App with Rotten Tomatoes API and SBJson Framework

We will create an app that will display a list of upcoming movies and their review scores in a table view. We will get our data from Rotten Tomatoes my favorite movie review site. But to be able to access their web service, we would need our own API key. We can get one by registering here: http://developer.rottentomatoes.com/


The Rotten Tomatoes API uses a RESTful service and it returns a JSON response. So to parse our response we would need to use the SBJson framework


Now, lets get started. Create a view based application in xcode. Name it "movies".

A Simple Tab Bar Application Tutorial

We are going to create a simple tab bar application, using the tab bar application template in xcode. Most of our UI will be done in interface builder, and we are only going to write a few lines of code.

This is how the final app is going to look like.
















So, lets get started.



Saturday, June 18, 2011

Creating a Flickr App Using NSXMLParser, UITableView and SOAP Tutorial

We will create an app that will search photos from flickr, put them in a table view, then display that photo in a webview. We will use SOAP to send our request to flickr. We will receive a corresponding SOAP response, which we will parse with NSXMLParser. There won't be a lot of explanations about the flickr API or about SOAP, I will just be running you through the creation process of this app.











Monday, April 11, 2011

New App soon to be on the App Store


Toy Car Crossing App
Toy Car Crossing is a free game which will soon be available for download in the App Store. Test your driving skills by driving an animated toy car through a busy street intersection, where other toy cars cross! Move the car using the accelerator pedal and stop it with the brake pedal. Use the shifter to move either forward or backward. Don’t forget to cross before the time expires. The game features five levels of challenging fun.
Supports retina display.
image
image