Profil de Libin绿色家园PhotosBlogListes Outils Aide

Blog


SQLite Resources for iPhone Developers

SQLite is a public domain database library that offers file and memory based relational database functionality from a single C library. The iPhone / iPod Touch has the SQLite library included and ready to roll and Apple expects the SQLite library to form the backbone of most applications’ data storage requirements.

We’ve collected together some of the best SQLite related tutorials, and libraries in order to help you on your way with this essential iPhone programming technology:

Tutorials

sqlite-tute1.pngiPhone SQLite Database Basics by Lee Falin is a comprehensive introduction to using SQLite in respect to iPhone application development. He covers SQLite database creation and iPhone specific database design considerations well. Lee’s tutorial has lots of screenshots and he takes a step-by-step approach that’s easy to follow. He walks through creating an SQLite database from scratch (on the desktop to start with) and then imports that into an XCode project. Bear in mind, however, that Lee’s tutorial is not about the actual coding necessary to use SQLite on the iPhone itself.

Reading data from a SQLite Database by Dean Collins is a wonderful “start to finish” tutorial that covers creating an SQLite database, creating an XCode project, and then all the code necessary to use that database within an iPhone app. There’s even a link to an archive of the code used in the tutorial so you can more quickly try it out for yourself.

SQLite Tutorial 1: Selecting Data by Jai Kirdatt is the first in five SQLite focused tutorials from the aforementioned author. This one covers creating an SQLite database and, like Dean’s tutorial above, using that database from Objective C. There’s more code and less screenshots than in the aforementioned tutorials, so this tutorial is worth coming to once you’re totally confident with the basics. Source code is available to download at the bottom of the post.

SQLite Tutorial 2: Deleting Data by Jai Kirdatt follows on nicely from the previous tutorial and quickly demonstrates how to delete rows of data from an SQLite database.

sqlite-tute2.pngSQLite Tutorial 3: Adding Data by Jai Kirdatt demonstrates how to add data to an SQLite database from Objective C.

SQLite Tutorial 4: Loading Data As Required by Jai Kirdatt shows how to select rows in a database to then display in a detail view. Data is only loaded when it is required.

SQLite Tutorial 5: Updating Data by Jai Kirdatt shows you how to update the database when fields on a form are edited and the application is then terminated.

Libraries

EntropyDB is an embedded object database for OS X 10.5 and iPhone OS written in Objective C that’s built on top of SQLite. It provides a nicer API than that offered by SQLite directly. You don’t need to use SQL at all, but instead just work with Objective C objects!

SQLitePersistentObjects allows you to call “save” on your objects and trust that they will be saved properly and can be easily reloaded in future. No SQL required.

FMDB is a library that acts as a wrapper around SQLite - inspired by JDBC. fmdb-migration-manager(originally by last week’s podcast interviewee - Dr Nic Williams) allows you to easily roll out database migrations using fmdb.

iPhone SQLite Persistence for Objects is an open source project that lets you add “object persistence” to your applications. The object persistence uses SQLite, and the library works on both the iPhone and iPod Touch.

Suggestions?

Know of any others? Leave a comment and we’ll do our best to include them!

SQLite + UITableView for iPhone

I see many people asking for SQLite tutorials around, and since I am using SQLite for the next part in the Advanced RSS Reader Tutorial, I thought I would write up a quick tutorial on using SQLite with the iPhone SDK.
1. Project Requirements
I suggest that you have at least a basic understanding of SQLite,writing SQL statements, the XCode interface and using the terminal inOSX. If you don’t know anything about any of these topics then thistutorial probably isn’t for you.
2. Creating our SQLite database for our tutorial
We first need to create a database for use with our application. Forthe purposes of this tutorial we will be building a database of animalsalong with a little information on them and a picture.
Fire up a new Terminal window and make a new folder to store the database in, here are the commands I ran
[pre]cd /Users/lookaflyingdonkey/Documents
mkdir SQLiteTutorial
cd SQLiteTutorial
sqlite3 AnimalDatabase.sql[/pre]You should now be at a “sqlite” command prompt, this is where wewill be building our database structure and entering some test data.
For our example we need the name of the animal, a short descriptionand a link to an image. Follow the commands below to create the tableand to enter some sample data.
[pre]CREATE TABLE animals ( id INTEGER PRIMARY KEY, name VARCHAR(50), description TEXT, image VARCHAR(255) );

INSERT INTO animals (name, description, image) VALUES ('Elephant', 'The elephant is a very large animal that lives in Africa and Asia', 'http://dblog.com.au/wp-content/elephant.jpg');
INSERT INTO animals (name, description, image) VALUES ('Monkey', 'Monkies can be VERY naughty and often steal clothing from unsuspecting tourists', 'http://dblog.com.au/wp-content/monkey.jpg');
INSERT INTO animals (name, description, image) VALUES ('Galah', 'Galahs are a wonderful bird and they make a great pet (I should know, I have one)', 'http://dblog.com.au/wp-content/galah.jpg');
INSERT INTO animals (name, description, image) VALUES ('Kangaroo', 'Well I had to add the Kangaroo as they are the essence of the Australian image', 'http://dblog.com.au/wp-content/kangaroo.jpg');[/pre]The first command will create the table with the required structureand the next four will insert some test data for us to work with. Toensure that you have entered the data correctly you can execute “SELECT* FROM animals;” and see if it returns the items above. Once you areconfident that everything had been created successfully you can leavethe sqlite command line by typing “.quit”.
3. Creating our Project
Now that our database is all ready to go we need to setup our X-Code project.
Start off by creating a new “Navigation-Based Application”.

Give your Project a name, I called mine “SQLiteTutorial”.
Now set your screen layout to how you prefer it, I suggest makingthe window as large as possible, and making the code view as tall aspossible by dragging the horizontal slider to the top. This will allowyou the most room to move when building your application.
Now its time to create the required classes and views for our application, we will start off by making our views.
Right Click on the “Resources” folder in the left hand pane andclick “Add File”, we want to create a new “View XIB” under the “UserInterfaces” group.

We now need to give it a name, to stick the Apple’s naming conventions we are going to call it “AnimalViewController.xib”, Now Click “Finish”.
Now we need to create two classes, the first one will represent ananimal, right click on the “Classes” folder in the left hand pane,click “Add > New File…”, choose the “NSObject subclass” templateunder the “Cocoa Touch Classes” group and name it “Animal”.
The second class will be for our AnimalsViewController, right clickon the “Classes” folder in the left hand pane, click “Add > NewFile…”, choose the “UIViewController subclass” under the “Cocoa TouchClasses” group and name it “AnimalViewController”.
4. Adding SQLite Framework and our Animal Database
Now that we have created all of our views and classes it is time to start the real grunt work.
First off we need to include the SQLite libraries so our applicationcan utilise them. To do this you will need to right click on the“Frameworks” folder in the left hand pane, then click on “Add >Existing Frameworks…”, then navigate to“/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.0.sdk/usr/lib/”and double click the “libsqlite3.0.dylib” file. A popup will appear,just click “Add” and the library will be added to your project.
We also need to add our database we created earlier to the Resourcesfolder, to do this simply right click on the “Resources” folder, click“Add > Existing Files…”, navigate to the location you created thedatabase in then double click on the AnimalDatabase.sql file. Anotherpopup will appear, just click add.
All done with the importing, time to code!
5. The Coding begins!
We are going to start the coding by building our “Animal” object,every animal will have 3 properties, a name, a description and an imageURL.
Open up the “Animal.h” file from the “Classes” folder and edit its contents to look like below,
[pre]#import <UIKit/UIKit.h>

@interface Animal : NSObject {
    NSString *name;
    NSString *description;
    NSString *imageURL;
}

@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *description;
@property (nonatomic, retain) NSString *imageURL;

-(id)initWithName:(NSString *)n description:(NSString *)d url:(NSString *)u;

@end
[/pre]Most of the above code should be pretty familiar to you, the only thing that may not be is the initWithName line, this line will allow us to create a new object with the required data, we could have used the default init function, but it will be easier for us to define our own.
Now we will actually have to implement the Animal Object, open up the “Animal.m” file and edit its contents to look like below:
[pre]#import "Animal.h"

@implementation Animal
@synthesize name, description, imageURL;

-(id)initWithName:(NSString *)n description:(NSString *)d url:(NSString *)u {
    self.name = n;
    self.description = d;
    self.imageURL = u;
    return self;
}
@end
[/pre]The above code should be pretty easy to read as well, it basicallystores the supplied data from the initWithName function and return theobject (self).
Now its time to setup the Application delegate to access the database.
Open up the “SQLiteTutorialAppDelegate.h” and edit its contents to look like below:
[pre]#import <UIKit/UIKit.h>
#import <sqlite3.h> // Import the SQLite database framework

@interface SQLiteTutorialAppDelegate : NSObject  {

    UIWindow *window;
    UINavigationController *navigationController;

    // Database variables
    NSString *databaseName;
    NSString *databasePath;

    // Array to store the animal objects
    NSMutableArray *animals;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@property (nonatomic, retain) NSMutableArray *animals;

@end
[/pre]What we are doing here is importing the SQLite database frameworkand creating some variables for storing the database details and anarray of animal objects.
Now open up the “SQLiteTutorialAppDelegate.m” file and edit its contents to look like below:
[pre]#import "SQLiteTutorialAppDelegate.h"
#import "RootViewController.h"
#import "Animal.h" // Import the animal object header

@implementation SQLiteTutorialAppDelegate

@synthesize window;
@synthesize navigationController;
@synthesize animals; // Synthesize the aminals array

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    // Setup some globals
    databaseName = @"AnimalDatabase.sql";

    // Get the path to the documents directory and append the databaseName
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [documentPaths objectAtIndex:0];
    databasePath = [documentsDir stringByAppendingPathComponent:databaseName];

    // Execute the "checkAndCreateDatabase" function
    [self checkAndCreateDatabase];

    // Query the database for all animal records and construct the "animals" array
    [self readAnimalsFromDatabase];

    // Configure and show the window
    [window addSubview:[navigationController view]];
    [window makeKeyAndVisible];
}

- (void)applicationWillTerminate:(UIApplication *)application {
    // Save data if appropriate
}

- (void)dealloc {
    [animals release];
    [navigationController release];
    [window release];
    [super dealloc];
}

-(void) checkAndCreateDatabase{
    // Check if the SQL database has already been saved to the users phone, if not then copy it over
    BOOL success;

    // Create a FileManager object, we will use this to check the status
    // of the database and to copy it over if required
    NSFileManager *fileManager = [NSFileManager defaultManager];

    // Check if the database has already been created in the users filesystem
    success = [fileManager fileExistsAtPath:databasePath];

    // If the database already exists then return without doing anything
    if(success) return;

    // If not then proceed to copy the database from the application to the users filesystem

    // Get the path to the database in the application package
    NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];

    // Copy the database from the package to the users filesystem
    [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];

    [fileManager release];
}

-(void) readAnimalsFromDatabase {
    // Setup the database object
    sqlite3 *database;

    // Init the animals Array
    animals = [[NSMutableArray alloc] init];

    // Open the database from the users filessytem
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
        // Setup the SQL Statement and compile it for faster access
        const char *sqlStatement = "select * from animals";
        sqlite3_stmt *compiledStatement;
        if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
            // Loop through the results and add them to the feeds array
            while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
                // Read the data from the result row
                NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
                NSString *aDescription = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
                NSString *aImageUrl = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];

                // Create a new animal object with the data from the database
                Animal *animal = [[Animal alloc] initWithName:aName description:aDescription url:aImageUrl];

                // Add the animal object to the animals Array
                [animals addObject:animal];

                [animal release];
            }
        }
        // Release the compiled statement from memory
        sqlite3_finalize(compiledStatement);

    }
    sqlite3_close(database);

}

@end
[/pre]Now I know that may look like a fair bit of code and it probablyalso looks quite scary! But really it is quite simple and I have triedto comment nearly every line to describe to you what the line does andwhy it is there.
The checkAndCreateDatabase function checks to seeif we have already copied our database from the application bundle tothe users filesystem (in their documents folder), if the databasehasn’t already been created or it has been removed for some reason itwill be recreated from the default database.
Next the readAnimalsFromDatabase function will makea connection to the database that is stored in the users documentsfolder, and then executes the SQL statement “SELECT * FROM animals”. Itwill then go through each row that is returned and it will extract thename, description and imageURL from the result and build an Animal object for each. You  will see the “sqlite3_column_text” function used here, there are many more of these for returning other field types such as “sqlite3_column_int” for integers, “sqlite3_column_blob” for blobs or “sqlite3_column_value” to get an unknown value.
Now that we have the data in our array and we have it in our known format we are ready to start displaying it.
Open up the “RootViewController.m” file and edit the numberOfRowsInSection to look like the following:
[pre]SQLiteTutorialAppDelegate *appDelegate = (SQLiteTutorialAppDelegate *)[[UIApplication sharedApplication] delegate];
return appDelegate.animals.count;
[/pre]What this does is it creates a link to the application delegate, andthen the second line returns the size f the animals array in outApplication delegate, this array was filled previously from the SQLitedatabase.
Now in the cellForRowAtIndexPath function you will need at change it to look like the following:
[pre]- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
    }

    // Set up the cell
    SQLiteTutorialAppDelegate *appDelegate = (SQLiteTutorialAppDelegate *)[[UIApplication sharedApplication] delegate];
    Animal *animal = (Animal *)[appDelegate.animals objectAtIndex:indexPath.row];

    [cell setText:animal.name];
    return cell;
}
[/pre]We pretty much just added 3 lines under the “// Set up the cell” line, the first one is the same as we added previously to access the application delegate. The second line creates a new Animalobject based on the array from the application delegate, it will beused to create a row for each individual record in the database. On thefinal line we are just setting the text of the cell to the name fieldfrom the Animal object.
You can now run the program and you should see a table view with the4 animals we added to the database, if you added more than my defaultanimals you should see them in here as well.
We will now setup the AnimalViewController, open up the “AnimalViewController.h” file and edit its contents to below:
[pre]#import <UIKit/UIKit.h>

@interface AnimalViewController : UIViewController {
    IBOutlet UITextView *animalDesciption;
    IBOutlet UIImageView *animalImage;
}

@property (nonatomic, retain) IBOutlet UITextView *animalDesciption;
@property (nonatomic, retain) IBOutlet UIImageView *animalImage;

@end
[/pre]What we are doing above is adding an outlet for the description and image for the Animal, we will use these later on when we link the view up.
Now open up the “AnimalViewController.m” file and add a synthesize call for for the description and image, this will go under the “@implementation AnimalViewController” line, like so:
[pre]#import "AnimalViewController.h"

@implementation AnimalViewController

@synthesize animalDesciption, animalImage;
[/pre]Now it is time to make the detailed view page appear when you selecta record. Open up the “AnimalViewController.xib” file from theresources folder and the interface builder should appear.
The first thing we need to do is to set the File’s Owner Class to AnimalViewController, this is done by selecting the “File’s Owner” item in the main window and then clicking Tools > Identity Inspector in the top menu, and then selecting AnimalViewController from the class dropdown.
Your inspector window should now look like this:

We are going to be using a UITextView for the description (as it will allow for word wrapping and scrolling in the case that the description is quite large) and a UIImageView to display the image. I have laid mine out like below:

Now that we have everything laid out it is time to link them all up, start by holding control and click+drag from the “File’s Owner” to the “View” objects, a little gray menu will appear and you will need to select view. Now hold control and click+drag from the “File’s Owner” to the UITextView in the layout window, you should see “animalDescription” in the popup list, select it. Repeat this process for the UIImageView and you should see animalImage appear, select it also.
Now save the interface and close the interface builder.
Nearly done! All we have to do now is to setup the code for when a user presses on a record in the table view.
Open up the “RootViewController.h” file and edit its contents to below:
[pre]#import <UIKit/UIKit.h>
#import "AnimalViewController.h"

@interface RootViewController : UITableViewController {
    AnimalViewController *animalView;
}

@property(nonatomic, retain) AnimalViewController *animalView; 

@end
[/pre]We are creating an instance of the AnimalViewController to be used bu the RootViewController when a user presses on an item.
Now open up the “RootViewController.m” file and edit the top part of the file to look like below:
[pre]#import "RootViewController.h"
#import "SQLiteTutorialAppDelegate.h"
#import "Animal.h"

@implementation RootViewController
@synthesize animalView;
[/pre]This will just synthesize the animalView that we just added.
First up lets set the default title of our view, to do this you needto uncomment the viewDidLoad function, and edit it to below:
[pre]- (void)viewDidLoad {
    [super viewDidLoad];
    // Uncomment the following line to add the Edit button to the navigation bar.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;

    self.title = @"My Zoo";
}
[/pre]We also need to edit the didSelectRowAtIndexPath
function in this file, edit it to look like below:
[pre]- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic -- create and push a new view controller
    SQLiteTutorialAppDelegate *appDelegate = (SQLiteTutorialAppDelegate *)[[UIApplication sharedApplication] delegate];
    Animal *animal = (Animal *)[appDelegate.animals objectAtIndex:indexPath.row];

    if(self.animalView == nil) {
        AnimalViewController *viewController = [[AnimalViewController alloc] initWithNibName:@"AnimalViewController" bundle:nil];
        self.animalView = viewController;
        [viewController release];
    }

    // Setup the animation
    [self.navigationController pushViewController:self.animalView animated:YES];
    // Set the title of the view to the animal's name
    self.animalView.title = [animal name];
    // Set the description field to the animals description
    [self.animalView.animalDesciption setText:[animal description]];
    // Load the animals image into a NSData boject and then assign it to the UIImageView
    NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[animal imageURL]]];
    UIImage *animalImage = [[UIImage alloc] initWithData:imageData cache:YES];
    self.animalView.animalImage.image = animalImage;

}
[/pre]What we are doing here is checking to see if the animalView object has already been created, if not then create it.
The next few lines are used to setup the animation (slide from rightto left) and to set the actual data fields to those of the selectedanimal.
Now you should be ready to fire up the application and see it in all its glory.
You should see your windows looking like below.
 
17 novembre

Useful open source libraries for IPhone Development

It’s been almost 3 months since the IPhone SDK’s infamous NDA restrictions were lifted, and there are now a good set of open source libraries available for the IPhone. In this post I will go through the ones that I know of one way or another. If you are aware of more high quality open source projects, please let me know in the comments so that I can update this post.

JSON Library

Currently, there are 3 choices that I know of:

JSON Framework: I used this one in one of my projects, and did not run into problems. Recently after the update to the new SDK 2.2, you may need to make a quick change to your project as outlined at the end of this discussion.

Touch JSON: This one is from the same project owners as the TouchXML.

Blake Seely’s BSJSONAdditions: This one is little older and intended for the Mac originally. According to the author of the JSON Framework a little slower as per his performance benchmarks

DOM XML Library

IPhone SDK includes an event driven (SAX based) XML parser called NSXMLParser. But if you need DOM style parser, you are out of luck unless you use the libxml2 library directly. There is no MacOS X equivalent of NSXML on the IPhone.

However luckily there are at least 2 options that I know of that you might use if you really need the DOM tree:

TouchXML: Open source lightweight replacement for Cocoa’s NSXML cluster of classes based onlibxml2.

Matt Gallagher: Wrote a lightweight wrapper on top of libxml2 and describes this in his blog entry.

However note that in a memory and CPU constrained environment like IPhone, it does make more sense to use an event driven parser (probably why Apple decided not to include NSXML in the first place). There is a recent SDK sample called XMLPerformance that shows parsing large number of items in an efficient way using both the NSXMLParser and the lower level SAX parser provided in libxml2.

Google Data APIs

So you would like to access Picasa, Google Calendar, Google Contacts and more… Well there is a very comprehensive ObjectiveC Client Library that you can include as a static library in your applications.

Twitter

Craig Hockenberry of the awesome Twitterific fame, made the source code of the Mobile Twitterific available to serve as a “Best Practices” document. There you can find how to connect to Twitter, get and post tweets etc.

Flickr

Unfortunately the well-known Cocoa API for Flickr is still not ported to the IPhone. However it looks like they are working on porting it to IPhone as of November 2008.

Game Engines

There are at least 3 game engines that I know of:

2D Gaming – Cocos 2D: This one is intended for 2D games, demos and other graphical/interactive applications. It is a port from the Python based cocos2d design. It uses Open ES 1.1, instead of the Quartz 2D and integrates the Chipmunk 2d physics engine.

3D Gaming – SIO2 Interactive: A 3D engine written in C using OpenGL ES.

3D Gaming – Oolong Engine: Mainly written in C++ with some ObjectiveC. Based on OpenGL ES 1.1 and includes the Bullet 3D physics engine.

You can also take a look at some IPhone game source code:

Tris: The source code for the Tetris clone that was pulled out of the Appstore earlier.

Molecules: This is not a game, but serves as a good tutorial for OpenGL ES development.

Unit Testing and Mock Frameworks

As of IPhone SDK 2.2, Apple now includes the OCUnit. This was discussed in the Stanford IPhone Application Programming course and you can download the presentation and the sample. So right of the bat you are now set up for unit testing, no more excuses.

Google actually has a more comprehensive framework in their Google Toolbox for Mac that even includes support for UI testing.

There is also a mock object framework called OCMock that is designed for MacOS X Cocoa, but witha little bit of work you can get that to work for your IPhone projects.