conedogers

Will code for race tires

Featured Image -- 1053


Leave a comment

Smalltalk about Objective-C


chrisw52:

This is a good review of Objective-C from a windows coder’s point of view.

Originally posted on codemouse:

Ok not so much a small talk, but more a ramble with an objective. (wow, geek humor is really bad).

Thats_the_joke

I’ve had the fortunate ability to spend the past 2 weeks or so getting ramped up on all things iOS and Objective-C for an internal project my company is working on. As a guy who has historically programmed in C-style languages and environments (.NET, Java, C/C++, and JavaScript), I thought this language would be pretty easy to pick up.  I was both right and wrong.

Of course, the core syntax of Objective-C IS almost exactly the same as C, which is great. For me to read through the code and understand which method was calling which other method and why and how, to follow the pointers and references, and the basic structure and syntax were all easy.  Then came the hard part.  Understanding both the Smalltalk-inspired messaging features that are…

View original 1,512 more words


Leave a comment

Watch out with assertions. Truth about NSAssert and assert functions in iOS.


chrisw52:

Some good tips on using the assertions in IOS

Originally posted on lines of code:

This article points out differences between NSAssert and assert functions in Objective-C. Let’s go for it.

An assertion is a predicate (a true–false statement) placed in a program to indicate that the developer thinks that the predicate is always true at that place. If an assertion evaluates to false at run-time, an assertion failure results, which typically causes execution to abort. – Wikipedia

We all know and use assertions. Or at least, we should. Most common are NSAssert and NSParameterAssert. Each thread has its own NSAssertionHandler object created for it. When invoked with an assertion, an NSAssertionHandler prints an error message that
includes the method and class (or function) containing the assertion and then it raises an
NSInternalInconsistencyException. There is also a assert() function defined in assert.h of the C Standard Library.

View original 180 more words


1 Comment

Using SQLite in your IOS applications part III


In this article we introduce a new feature into the example application that was built in the last article  “Using SQLite in your IOS applications part II” that will allow us to explore different data types found in SQLite.  A photo of the contact will be added to the database.

modify storyboards

the first step is to add a UIimageView to the AddContactViewController, ViewContactViewController, and the UpdateContactViewController panes in the storyboard.

  • Add a new section and change the title to “Photo”.
  • drag a UIImageView onto the new tableViewCell in the photo section and resize to suite your tastes

Add a new UIImageView to the app to display the contacts photo

Once you have modified the storyboards, we need to hook up the UIImageView to a property within each controllers class object.

In each of the controller classes, we add the following property

@property ( nonatomic, weak ) IBOutlet UIImageView *photo;

After adding the property, remember to connect the IBOutlet for each photo property to their UIImageViews on the storyboard.  When that is done, compile the code to fix and build errors or warnings, and we are done here.

Modify database schema

For this sample, we introduce a new data type into the schema.  The new database scheme  introduces a new SQL data types supported by SQLite, the blob.  Blobs are primarily used for storing binary data, like photos and short videos, audio, etc..  Basically, a blob can hold any piece of data that cannot be represented by any of the other SQL data types supported by SQL.  For this sample we are using a blob to story a PNG image of a contact.

     TABLE Contacts (idx INTEGER NOT NULL DEFAULT 0 PRIMARY KEY AUTOINCREMENT,
         firstname Varchar DEFAULT NULL,
         lastname Varchar DEFAULT NULL,
         phone Varchar DEFAULT NULL,
         photo BLOB DEFAULT NULL);

If you have decided to try and modify the code from the previous sample, you will need to alter the database instead of creating a new one. To do this, we need to add code to the SQLiteManager class to alter the Contacts table to include the Blob for the photo.

    NSString *path = [self databasePath];

    // if the path does not exist, then we need to initialize the database.
    if ([fileManager fileExistsAtPath:path] == YES)
    {
        // check to see if we have attempted to upgrade the database before.
        // we only want to run the ALTER command once after an upgrade.
        if ( [[NSUserDefaults standardUserDefaults] boolForKey:@"FirstRun"] == NO) {
            // the file exists, so all we need to do is alter the existing table.
            sqlite3 *database = [self newConnection];
            // the database file does not exist, so we need to create one.
            if (database)
            {
                // load the SQL commands that will create the database
                NSString *sqlCommands = @"ALTER TABLE Contacts ADD photo BLOB DEFAULT NULL;";

                // any error message that sent back from sqlite when creating the database will go here.
                char *szErrorMessage = NULL;

                // execute the sql commands
                int error = sqlite3_exec(database, [sqlCommands UTF8String], NULL, NULL, &szErrorMessage);

                if (error == SQLITE_OK)
                {
                    NSLog(@"successfully created database");
                    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"FirstRun"];
                }
                else {
                    NSLog(@"Failed with error %s", sqlite3_errmsg(database));
                }

                [self closeConnection:database];
            }
        }
    }

All we do here is add a new Blob to the end of the table record. Which brings up an important point. It is safer to Add new records to a table, but deleting columns can be problematic with the underlying flat file system used to store the physical database on the file space in your device. So be careful when modifying your tables.

Code changes for photos

The next step is to modify the Person object to include a UIImage to hold the photo retrieved from the database.  Each of the categories that were implemented are affected and need to be changed to accommodate the photo column retrieved in each SQL query.

Person object modifications

In the person.h header file, add a property for the photo, and declare the overloaded setter selector for the photo property.

@property (nonatomic, copy) UIImage  *photo;

-(void) setPhoto:(UIImage *)value;

In the person.m file we add the implementation for the setPhoto selector.

-(void) setPhoto:(UIImage *)value
{
    if (photo == nil) {
        photo = value;
    }
    else {
        photo = value;
        self.dirty = YES;
    }
}

With these changes the person object can now track the photo of the contact in the database.  Now we need to look at the categories that are affected by the changed database schema.

Person (AddNewPerson)

In the last article, we used a SQL string to insert records into the database. This time we use sqlite3_bind functions to bind the parameters in the prepared statement that is ready to execute. The process is really very simple. The column data is filled in left to right, each column is identified numerically.
With simple data types like integers and floating point numbers, the binding is straight forward. Like strings, we need to label the blob data as SQLITE_TRANSIENT to signal the database engine on how to treat the memory we are passing to it. When inserting large pictures, these transactions can take time. this is a good candidate for a background thread or something to be scheduled as a background task on the run loop.


+(id)addNewPersonWithFirstName:(NSString *)firstName LastName:(NSString *)lastName phoneNumber:(NSString *)phoneNumber andPhoto:(UIImage *)photo intoDatbase:(sqlite3 *)database
{
    Person *contact = nil;

    // here we build a string for the complete SQL query and values to insert.
    NSString *query = @"INSERT INTO Contacts (firstname, lastname, phone, photo) VALUES (?,?,?,?)";
    int success = -1;
    sqlite3_stmt *statement = nil;

    int error = sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL);
    if ( error != SQLITE_OK)
    {
        // error
        NSLog(@"Error failed to prepare sql with err %s", sqlite3_errmsg(database));
    }
    else
    {
        // Now bind the variable to the prepared statement
        sqlite3_bind_text(statement, 1, [firstName UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 2, [lastname UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 3, [phoneNumber UTF8String], -1, SQLITE_TRANSIENT);

        // now we store the image into the database as a PNG for better compression.
        sqlite3_bind_blob(statement, 4, [UIImagePNGRepresentation(photo) bytes], [UIImagePNGRepresentation(photo) length], SQLITE_TRANSIENT);

        // execute the query
        success = sqlite3_step( statement );
        if ( success == SQLITE_DONE )
        {
            // successful insertion into the database, now create the person object.
            success = (int)sqlite3_last_insert_rowid(database);
            contact = [[Person alloc] initWithPrimaryKey:success AndDatabase:database];
            contact.first = firstName;
            contact.last = lastName;
            contact.phone = phoneNumber;
            contact.photo = photo;
        }
    }

    // cleanup
    sqlite3_finalize(statement);
    statement = NULL;

    return contact;
}

 

Person (ReadPersons)

The modifications to the read persons category are pretty easy.  We have to modify the SQL SELECT statement to include the photo.

        sqlite3_stmt *statement = NULL;

        int error = sqlite3_prepare_v2(database, "SELECT idx, firstname, lastname, phone, photo FROM Contacts", -1, &statement, NULL);

then we process the bytes retrieved from the query results and put them into a UIImage for local storage.

                UIImage *photo = nil;

                // We need two parameters to get the BLOB data.  the actual blob and the length in bytes.
                NSData *imageData = [NSData dataWithBytes:sqlite3_column_blob(statement, 4) length:sqlite3_column_bytes(statement, 4)];
                if (imageData) {

                    // got it, stuff it into a UIImage
                    photo = [UIImage imageWithData:imageData];
                }

                // insert into an object
                Person *contact = [[Person alloc] initWithPrimaryKey:primaryKey AndDatabase:database];
                if (contact) {
                    contact.first = firstName;
                    contact.last = lastName;
                    contact.phone = phone;
                    contact.photo = photo;

                    [results addObject:contact];
                }

Person (WritePerson)

Writing the photo out is just as easy.  We need to get the photo represented in a byte sequence for storage in a blob.  To do this on IOS we need to get access to the raw bytes stored within the UIImage.  The IOS SDK provides a pair of functions UIIMagePNGRepresentation() and UIImageJPEGRepresentation().  These functions return a NSData Object that will have a pointer to either the Jpeg or PNG representation of the UIImage.  From there we can use the NSData object to get access to the raw bytes and the length in bytes of the image.

First we modify the prepared statement.
        sqlite3_stmt *statement = NULL;

        const char *query = "UPDATE Contacts SET firstname = ?, lastname = ?, phone = ?, photo = ? WHERE idx = ?";
        error = sqlite3_prepare_v2(_database, query, -1, &statement, NULL);
Bind the image to the blob.  Make sure to label the memory properly so the database engine knows how to handle it properly, there is no automatic garbage collection here.
            // now we store the image into the database as a PNG for better compression.
            sqlite3_bind_blob(statement, 4, [UIImagePNGRepresentation(self.photo) bytes], (int)[UIImagePNGRepresentation(self.photo) length], SQLITE_TRANSIENT);
            sqlite3_bind_int(statement, 5, (int)self.primaryKey);

Once you have bound the image to the SQL prepared statement, you can execute it. This can be time consuming, so like the AddNewPerson category, this is a good candidate for background processing.

Implement UIImagePickerController

the only thing left to do is implement the UIImagePickerController.  This class is used to select photos, take video, or use the camera to take snapshots, which is what we are going to do here.  Implementing this controller we step outside the storybook code and implement this controller manually.

To implement the control we need to implement the protocols from the UIImagePickerControllerDelegate, UINavigationControllerDelegate, and the UIActionSheetDelegate to present a simple choice dialog.

@interface AddContactViewController : UITableViewController <uiimagepickercontrollerdelegate, uiactionsheetdelegate,="" uinavigationcontrollerdelegate="">
@property (weak, nonatomic) IBOutlet UITextField *firstName;
@property (weak, nonatomic) IBOutlet UITextField *lastName;
@property (weak, nonatomic) IBOutlet UITextField *phone;
@property (weak, nonatomic) IBOutlet UIImageView *photo;

@property (nonatomic, assign) sqlite3 *database;

@property (nonatomic, weak) id delegate;

-(IBAction)cancel:(id)sender;
-(IBAction)done:(id)sender;
-(void)takePhoto;

@end

We also add a new selector takePhoto. In this method we implement the action sheet that we use to let the user select what kind of photo to take.
The result of the action sheet is used to configure the UIImagePickerController.

#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    BOOL bCancel = NO;
    UIImagePickerController *photoPicker = [[UIImagePickerController alloc] init];
    photoPicker.delegate = self;
    photoPicker.allowsEditing = YES;

    // we are processing a photo
    switch (buttonIndex)
    {
        case 0: // take photo
        {
            if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
                photoPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
            }
            break;
        }
        default:
            // cancel
            bCancel = YES;
            break;
    }
    if ( !bCancel )
    {
        // present the view controller.
        [self presentViewController:photoPicker animated:YES completion:nil];
    }
}

Once we have configured the UIImagePickerController the UIActionSheetDelegate launches the view. Once the view has loaded, you will be able to take a picture.  The slideshow gallery demonstrates the application flow.

This slideshow requires JavaScript.

Once you have picked a photo or canceled, the UIImagePickerController will signal one of protocols that it defines. Pretty simple really, there are two protocol methods to implement, one for success, the other for canceling.

#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *selectedImage = (UIImage *)[info valueForKey:UIImagePickerControllerEditedImage];
    if ( selectedImage != nil )
    {
        self.photo.image = selectedImage;

    }
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

implementing the UIImagePickerController is really not too difficult. Once you have the code hooked up, we need a way to call the action sheet. For this example, the selecting of a table cell is used to invoke the action sheet.


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // make sure we only invoke the UIImagePickerController on the photo table view cell.
    if (indexPath.row == 0 && indexPath.section == 0) {
        [self takePhoto];
    }
}

-(void)takePhoto
{
    UIActionSheet *dialog = nil;

    // present the action sheet that offers the user the choices for photos.
    // open a dialog with an OK and cancel button
    dialog = [[UIActionSheet alloc] initWithTitle:@""
                                         delegate:self
                                cancelButtonTitle:@"Cancel"
                           destructiveButtonTitle:nil
                                otherButtonTitles:@"Take Photo", @"Choose Existing Photo", @"Edit Photo", nil];

    dialog.actionSheetStyle = UIActionSheetStyleBlackTranslucent;

    // show the action dialog on top of the photo.
    [dialog showFromRect:self.photo.frame inView:self.view animated:YES];

}

And that’s it. Using blobs in your SQLite database is really quite easy, almost as easy as handling string data.

Source code

The source code for this blog entry is available on GitHub.

references

IOS Human interface guidelines : Modal Contexts

Binary Data Programming guide for Cocoa

IOS developer library : About the Camera and Photo Library

SQLite

 

Using SQLite in your IOS applications part II

Using SQLite in your IOS applications part I

Building Sqlite into your IOS applications 


Leave a comment

9 steps to Create a Successful Gaming App!


chrisw52:

This is a pretty good checklist for any mobile app, not just games.

Originally posted on Gre8ive Apps:

You dream to create a gaming app and make big bucks from it. Wondering what it takes? All you need is the desire and a game plan. Let’s not waste time. Begin now!

1. Do market research.


 

  • The most critical factor is your understanding of the market place for any business. To begin with, you can check out App Store which is loaded with array of categories.
  • The first and foremost thing to do is to get the feel of the market. Become an app addict. Invest your time in training period, studying about the successful apps and playing them as they will tell you volumes about market. The more number of hours you spare studying them the better image you retrieve about their common traits and the desirability of users. Maintain notes for an app’s success are its ranking and consistency.
  • Figure out what people want and…

View original 851 more words


3 Comments

Using SQLite in your IOS application part II


In my previous article Using “SQLite in your IOS application Part I” introduced a new sample application that utilized an IOS static library containing the latest SQLite amalgamation source code.  In the sample application, a pair of classes were created for wrapping the basic SQLite functionality into Objective-C.  These classes were used to create and open a database.  Now that we have that database created and we have the code to open and close it, now we need to add the basic operations on a database.  In this article we will take the SQLiteManager and SQLiteObject classes and implement them in a better MVC architecture and add the capabilities to Add, Delete, and update records in a table.

SQLite classes

Just as a review, here are the classes that were introduced in the last article.  “SQLite in your IOS application Part I” introduced a pair of new classes that are designed to be used for SQLite database interaction.  That sample code really only covered the first class, the SQLiteManager which does not do that much.  In this sample code we are focusing on the second class, the SQLiteObject.  This class is really the main part of the application.

SQLite Manager

The SQLite manager class is a simple class that creates the pointer to the SQLite database instance.  The SQLiteManager class manages the database connection while the SQLiteObject class manages the queries against the database.  This class controls the initialization of the database on the first run of the application and maintains that connection for the lifetime of the application.  In the last example, we opened and closed the database connection on demand.  While this does work, leaving the connection open avoids hitting the file system.  It is possible to have multiple database connections open at one time, so tracking which database connection you queried your object against is important. The SQLiteObject is designed to track the open database connection because that object works directly with the data stored within the database.

@interface SQLiteManager : NSObject

+(void) initializeDatabase;
+(NSString *) databasePath;
+(sqlite3 *) newConnection;
+(sqlite3 *) newConnectionFromFilename:(NSString *)databaseFilePath;
+(void) closeConnection:(sqlite3 *)database;
@end
SQLiteObject methods
  • +(void) initializeDatabase - This method initializes the database on the first run.  Inside this method we create the database file and populate the database with a table and add records to the table for this sample.
  • +(NSString *) databasePath - A method to return the absolute path to the database file on the IOS device.
  • +(sqlite3 *) newConnection - Open a new connection to the database.  If the database file has not been initialized, this will create it.  This will cause the initializeDatabase to fail if called before the database is initialized.
  • +(sqlite3 *) newConnectionFromFilename:(NSString *)databaseFilePath - open a database located at the absolute path in databasePath.
  • +(void) closeConnection:(sqlite3 *)database - close an open database connection.

SQLiteObject

The SQLite object class is a class that queries the database and tracks individual records retrieved from the database.  By itself, the SQLiteObject class does not contain any methods that directly query against the database connection held by its database property.  The real functionality resides within the class object that derives off this base class.  In this example, we have the Person Class which is derived from this SQLite class.  In the previous example the person object was not modified to run any queries against the database, we only used it to track the open connection and the primary key of the record.  Now we are going to add more methods to complete the missing database functionality.

@interface SQLiteObject : NSObject {
    sqlite3 *_database;
    NSInteger _primaryKey;
    BOOL      _dirty;
}
@property (assign, nonatomic, readonly) NSInteger primaryKey;
@property (nonatomic, readonly) sqlite3 *database;
@property (nonatomic, assign) BOOL dirty;

-(id) init;
-(id) initWithPrimaryKey:(NSInteger)pk database:(sqlite3 *)db;
-(BOOL) isConnected;

@end
SQLiteObject Properties
  • primaryKey - the primary key on this record item.
  • database - The database connection handle used to query this record.
  • dirty - Boolean flag to determine if the data on this object has changed.
SQLiteObject methods
  • -(id) init - initialize a blank SQLiteObject
  • -(id) initWithPrimaryKey:(NSInteger)pk database:(sqlite3 *)db - initialize a new SQLiteObject with a primary key and database connection handle.
  • -(BOOL) isConnected - returns YES if the primary key and database connection handles are valid.

Person Class

The Person class contains the data retrieved from each record.  It is derived from the SQLiteObject class and it contains properties that define each record value retrieved from the database.  The Person object is a very small and light weight object.  It is designed to be small in size so it can easily and efficiently passed around to the different views that manipulate each object instance.

@interface Person : SQLiteObject

@property (nonatomic, copy) NSString *first;
@property (nonatomic, copy) NSString *last;
@property (nonatomic, copy) NSString *phone;

@end
Person Properties
  • primaryKey – the primary key inherited from SQLiteObject
  • database – The database connection handle inherited from SQLiteObject.
  • dirty – Boolean flag inherited from SQLiteObject.
  • first – Contacts first name as a NSString
  • last – Contacts last name as a NSString
  • phone – Contacts phone as a NSString

 

Person Categories

In the last article “SQLite in your IOS application Part I“, we modified the Person class so it was derived from a SQLiteObject. All this did was to make the Person class SQLite aware, but no methods were implemented for the person class to access the database. At this point, the Person class tracks the primary index of the object in the SQL result set, and the opened database connection that was used in the last query.  The real functionality behind the person object is provided via categories.  Objective-C categories offer a good way to implement the database functionality we are looking for while keeping the base Person object lean and mean which helps keep our memory usage down.

Categories and SQLite operations

Categories are used to break down the  SQL operations into functional groups of selectors that are only defined within the scope of the source file in which the category was included.   For this example, we are going to use the following categories.  Most of the methods implemented in the categories are static, only the update method is implemented off the current instance.

// from Person+AddNewPerson.h
@interface Person (AddNewPerson)
+(id)addNewPersonWithFirstName:(NSString *)firstName LastName:(NSString *)lastName andPhone:(NSString *)phoneNumber intoDatbase:(sqlite3 *)database;
@end

// from Person+DeletePerson.h
@interface Person (DeletePerson)
+(void)deletePersonWithIndex:(NSInteger)index fromDatabase:(sqlite3 *)database;
@end

// from Person+ReadPersons.h
@interface Person (ReadPersons)
+(NSMutableArray *)getAllPersonsFromDatabase:(sqlite3 *)database;
@end

// from Person+WritePerson.h
@interface Person (WritePerson)
-(int)updateTheDatabase;
@end

To implement each of these categories in the IOS application we need to include the appropriate header in the source file where we need the functionality.  Before we talk about how the categories are implemented in the IOS sample application, we need to talk about the application itself first.

Application design

This sample is written using a storybook that manages a series of table views.  We’re not going to spend a whole lot of time on how to build the storybook here.  If you are curious, you can check out this good blog I found on the subject. “Storyboards tutorial in IOS7“.  That blog article does a good job at describing the tasks required to create the storyboard application we want using UINavigationController with UITableViewControllers.

  • The Application delegate implements the ReadPerson and WritePerson categories.
  • The Contacts View controller  implements the Read and Delete categories
  • The AddContactViewcontroller  implements the Add New Person category.
  • The Update view controller implements the Write Person category.

 

Screen Shot 2014-03-22 at 11.15.48 AM

The storybook layout for the sample application

Creating the storyboards is one of the easier tasks in this sample application.  Storyboards are nice because they let you get a running prototype up quickly.  Once you have the prototype all we need to do is plug in the calls to the SQLite classes and objects and we have an app!

Opening the database

In this sample, we put the main database connection into the application delegate so we can handle the main IOS events for launching, entering the background, and termination.  The application delegate contains two private variables, the database connection pointer and the list of contacts retrieved from the last query into the database.

@implementation AppDelegate {
    NSMutableArray *_contacts;

    sqlite3 *_database; // the pointer to the open database connection.
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // initialize database on first run.
    [SQLiteManager initializeDatabase];

    _database = [SQLiteManager newConnection];  //open the database
    _contacts = [Person getAllPersonsFromDatabase:_database];

    UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
    ContactsViewController *contactsViewController = [navigationController viewControllers][0];
    contactsViewController.contactList = _contacts;
    contactsViewController.database = _database;

    return YES;
}

Opening the database is easy, we first have to check to see if the database has been installed correctly, then we can initialize a new database connection.  To get the list of contacts from the database, we use the ReadPersons category from the Person object.

#import "Person+ReadPersons.h"

@implementation Person (ReadPersons)

+(NSMutableArray *)getAllPersonsFromDatabase:(sqlite3 *)database
{
    NSMutableArray *results = nil;
    if (database) {
        // now we have opened the database, retrieve some records.
        sqlite3_stmt *statement = NULL;

        // execute the Sql statement
        int error = sqlite3_prepare_v2(database, "SELECT idx, firstname, lastname, phone FROM Contacts", -1, &statement, NULL);

        if (error == SQLITE_OK) {
            // got some results, now parse the records returned.
            results = [[NSMutableArray alloc] init];

            while (sqlite3_step(statement) == SQLITE_ROW) {
                // get the primary key
                int primaryKey = sqlite3_column_int(statement, 0);

                // get the data
                NSString *firstName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
                NSString *lastName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 2)];
                NSString *phone = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 3)];

                // insert into an object
                Person *contact = [[Person alloc] initWithPrimaryKey:primaryKey AndDatabase:database];
                if (contact) {
                    contact.first = firstName;
                    contact.last = lastName;
                    contact.phone = phone;

                    [results addObject:contact];
                }
            }
        }
        // clean up the SQL statement when your done.
        sqlite3_finalize(statement);
        statement = NULL;
    }
    return results;
}
@end

if for what ever reason you are not using ARC, then you need to be careful about handing the strings and other data that might have blocks of memory to move around. The string data returned by SQLite is managed by a different memory pool than the rest of your IOS environment.  Internally, the string data should be treated as SQLITE_TRANSIENT by default.  This means that we treat the strings as volatile, so we would need to retain the strings as they are extracted from the result set.  ARC takes care of this automatically.

Adding a new record

Adding a new record to the Contacts table is done through the Add Person View controller.  The AddContactViewController has 2 methods for handling the navigation bar button events for “Cancel” and “Done”.  The cancel action is self evident, all it does is close the view.  The done action performs the actual record insert before closing the view.

-(IBAction)done:(id)sender
{
    // Create a new Person object and insert it into the database
    Person *person = [Person addNewPersonWithFirstName:self.firstName.text
                                              LastName:self.lastName.text
                                              andPhone:self.phone.text
                                           intoDatbase:self.database];

    // cause the calling tableView controller to reubild it's data.
    [self.delegate addContactViewControllerDidAddContact:self didAddContact:person];

}

Inserting into the database with simple datatypes is easy enough. For this sample, we are just constructing a string that contains all the values within the string. This is impractical for large amounts of data in strings or blobs, but for now it will work.

#import "Person+AddNewPerson.h"

@implementation Person (AddNewPerson)

+(id)addNewPersonWithFirstName:(NSString *)firstName LastName:(NSString *)lastName andPhone:(NSString *)phoneNumber intoDatbase:(sqlite3 *)database
{
    Person *contact = nil;
    NSString *query = [NSString stringWithFormat:@"INSERT INTO Contacts (firstname, lastname, phone) VALUES ('%@','%@','%@')", firstName, lastName, phoneNumber ];
    int success = -1;
    sqlite3_stmt *statement = nil;

    int error = sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL);
    if ( error != SQLITE_OK) {
        // error
        NSLog(@"Error failed to prepare sql with err %s", sqlite3_errmsg(database));
    }
    else
    {
        success = sqlite3_step( statement );
        if ( success == SQLITE_DONE ) {
            // successful insertion into the database, now create the person object.
            success = (int)sqlite3_last_insert_rowid(database);
            contact = [[Person alloc] initWithPrimaryKey:success AndDatabase:database];
            contact.first = firstName;
            contact.last = lastName;
            contact.phone = phoneNumber;
        }
    }
    sqlite3_finalize(statement);

    return contact;
}
@end

Deleting a record

Deleting a record is done through deleting table cells on the contacts view.  The edit button enables or disables the UITableView editing feature.  Once we have deleted a cell the application is notified with a call to the following method.

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        int index = (int)indexPath.row;
        // get the person
        Person *person = (Person *)[_contactList objectAtIndex:index];
        if (person) {

            // delete the person from the database.
            [Person deletePersonWithIndex:person.primaryKey fromDatabase:person.database];
            // now remove it from the datasource for the tableview.
            [_contactList removeObject:person];
        }
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
}

Deleting a record is easy. When the application commits the changes to the UITableView, we update the list of contacts, and with the retrieved person object, we delete the record from the database.  We use the primary key to identify the record to delete, and your done.

@implementation Person (DeletePerson)

+(void)deletePersonWithIndex:(NSInteger)index fromDatabase:(sqlite3 *)database
{
    const char *query = "DELETE FROM Contacts WHERE idx=?";
    sqlite3_stmt *statement = NULL;
    int error = sqlite3_prepare_v2(database, query, -1, &statement, NULL);
    if ( error != SQLITE_OK){
        // error
        NSLog(@"Error failed to prepare sql with err %s", sqlite3_errmsg(database));
    }

    // bind the primary index to the statement
    sqlite3_bind_int(statement, 1, index);
    // execute the statement
    sqlite3_step( statement );
    // clean up
    sqlite3_finalize(statement);
    statement = NULL;
}

@end

 

Updating a record

Updating a record is a little more tricky. The SQLiteObject has a dirty flag that needs to be set before you can trigger an update. You can certainly hack the object and manually set the dirty flag when you want too. A better method is to overload the setter method when the property is synthesized.  Overloading the synthesized getter method lets us automatically set the dirty flag when we want to with little changes to the code.

Modify the person object

In the Person object we want to modify the source to include the overloads after creating synthesizer statements for each of the properties used in the person object.

@implementation Person

@synthesize first;
@synthesize last;
@synthesize phone;

// let the database connection know that something has changed
// by overloading the setters that are created by the @systhesize.
// now we can update the database anytime values change in the object.

-(void) setFirst:(NSString *)value
{
    if (first == nil) {
        first = value;
    } else if ([first compare:value] != NSOrderedSame) {
        first = value;
        self.dirty = YES;
    }
}

-(void) setLast:(NSString *)value
{
    if (last == nil) {
        last = value;
    } else if ([last compare:value] != NSOrderedSame) {
        last = value;
        self.dirty = YES;
    }
}

-(void) setPhone:(NSString *)value
{
    if (phone == nil) {
        phone = value;
    } else if ([phone compare:value] != NSOrderedSame) {
        phone = value;
        self.dirty = YES;
    }
}
@end

That’s all the changes we need to support the updating of records in the Person object. Now anytime one of the properties changes in value, we set the dirty flag for that object instance. We do not set the dirty flag when the property is nil because that is the first assignment when the current object instance is first created. This only happens on the first application load, or when a new object is added to the database.

@implementation Person (WritePerson)

-(int)updateTheDatabase
{
    int error = SQLITE_OK;

    if ([self isConnected] && _dirty) {
        sqlite3_stmt *statement = NULL;
        const char *query = "UPDATE Contacts SET firstname = ?, lastname = ?, phone = ? WHERE idx = ?";
        error = sqlite3_prepare_v2(_database, query, -1, &statement, NULL);
        if (error != SQLITE_OK) {
            NSLog(@"Error failed to prepare sql with err %s", sqlite3_errmsg(_database));
        }
        else{
            // bind the data to the query.  We need to make sure that we label the string
            // data as SQLITE_TRANSIENT so that SQLite knows how to handle the memeory.
            // the order of the binding is the order of the values on the update query string.
            sqlite3_bind_text(statement, 1, [self.first UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_text(statement, 2, [self.last UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_text(statement, 3, [self.phone UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_int(statement, 4, self.primaryKey);

            // execute the query
            error = sqlite3_step(statement);
            if (error != SQLITE_DONE) {
                NSLog(@"Error failed to save with err %s", sqlite3_errmsg(_database));
            } else _dirty = NO;  // data was written to the database, reset dirty flag.
        }
        sqlite3_finalize(statement);
    }
    return error;
}
@end

Updates are used to save the list of objects in the application delegate when we receive moving into background and termination events.  This should not be necessary with the approach this example takes.  Any time that data is changed we immediately write the data to the database to prevent data loss.  That said, for redundancy we add some extra calls to update the contacts in the list stored in the application delegate.


- (void)applicationDidEnterBackground:(UIApplication *)application
{
// save out any updates in the contacts array. Any person object marked as dirty, will be updated to the database.
[_contacts makeObjectsPerformSelector:@selector(updateTheDatabase)];
}

- (void)applicationWillTerminate:(UIApplication *)application
{
// save out any updates in the contacts array. Any person object marked as dirty, will be updated to the database.
[_contacts makeObjectsPerformSelector:@selector(updateTheDatabase)];

// close the opened database connection
[SQLiteManager closeConnection:_database];
_database = NULL;
}

Updating all the objects is really easy with Objective-C and its fast enumeration. To flush the data out to the database, we call the updateDatabase selector on all the objects in the list. If any objects have been marked dirty, they are written out to the database.

That’s it! it is really easy to integrate SQLite into your IOS application. Included with this blog entry is a copy of the working project that you can take a look at. I would recommend that you look at the app, this blog was written in 3 languages. English, Objective-C, and C/C++. Everything is crystal clear in the computer languages, the english lost a bit in translation. so please take a look at the sample code

Source code is located on GitHub, SQLiteExamplePart2

Links & references

Programming With Objective-C – Customizing existing classes

Tutorial: Storyboards

Storyboard tutorial in IOS7

SQLite

Using SQLite in your IOS applications Part I

Building SQLite in your IOS applications

 


3 Comments

Using Sqlite3 in your IOS application part 1


This blog entry covers how to incorporate a SQL database into your IOS application using Sqlite.  In my previous blog entry “Building SQLite into your IOS applications”, we built a static library from the latest SQLite Amalgamation source code.  Now we will build a test application to test the library.

xcode project setup

For this sample we will be using a simple UITableView. each row of the table will contain a record retrieved using a standard SQL query against a locally installed SQLite database.

project requirements

The database will be located within the applications folder space on the device.  It will contain a single table that will hold the following records

  1. first name
  2. last name
  3. phone number

Each table entry will be represented with a UITableViewCell.  Each row entry will display first and last name.  clicking the cell will present a view that display the entire first name, last name, and phone number of the selected row.  The user will be able to add new records by reusing the same view used to display the records, but with editing enabled on the UITextFields.

create the application

For the test application we are going to use a basic TableView application to view the records out of the database.  For this example, we are only creating, inserting into and reading a database.

adding database support to the app

If you read the previous blog entry “Building SQLite into your IOS applications”, there we setup an Xcode project that builds a static library of the latest SQLite Amalgamation source code.  Assuming you use the latest source code from Sqlite.org, then you will have the latest available.  This version will be much newer than anything that ships with the IOS SDK.  There are two methods to add the static library to the test app.  In a production environment, we would take the static library and add it through the Linked framework and Library settings under your project general settings.  this would require that you change the default output folder for the library which is something we have not done in the SQLite static library project yet.  That leaves us with the second method of including the SQLite project as a subproject of the test app.  This is also the easiest to set up but comes at a small cost of the extra build time to build the SQLite project each time you rebuild the test app.

SQLite classes

I use two classes to implement the SQLite database in your source code.  The first class manages the database connection while the other class manages the queries against the database.

The SQLite manager class is a simple class that creates the pointer to the SQLite database instance.   This class is also controls the initialization of the database on the first run of the application.  When the application is first deployed, we need to create the database, and for the purpose of this sample, fill it with data that will be displayed on the table view.

@interface SQLiteManager : NSObject

+(void) initializeDatabase;
+(NSString *) databasePath;
+(sqlite3 *) newConnection;
+(sqlite3 *) newConnectionFromFilename:(NSString *)databaseFilePath;
+(void) closeConnection:(sqlite3 *)database;
@end
  • +(void) initializeDatabase – This method initializes the database on the first run.  Inside this method we create the database file and populate the database with a table and add records to the table for this sample.
  • +(NSString *) databasePath – A method to return the absolute path to the database file on the IOS device.
  • +(sqlite3 *) newConnection – Open a new connection to the database.  If the database file has not been initialized, this will create it.  This will cause the initializeDatabase to fail if called before the database is initialized.
  • +(sqlite3 *) newConnectionFromFilename:(NSString *)databaseFilePath – open a database located at the absolute path in databasePath.
  • +(void) closeConnection:(sqlite3 *)database – close an open database connection.

The SQLite object class is a class that queries the database and tracks individual records retrieved from the database.  This class is intended to be used as a parent class to a derived class that represents a table in the database.

@interface SQLiteObject : NSObject {
    sqlite3 *_database;
    NSInteger _primaryKey;
    BOOL      _dirty;
}
@property (assign, nonatomic, readonly) NSInteger primaryKey;
@property (nonatomic, readonly) sqlite3 *database;
@property (nonatomic, assign) BOOL dirty;

-(id) init;
-(id) initWithPrimaryKey:(NSInteger)pk database:(sqlite3 *)db;
-(BOOL) isConnected;

@end

SQLiteObject Properties

  • primaryKey – the primary key on this record item.
  • database - The database connection handle used to query this record.
  • dirty – Boolean flag to determine if the data on this object has changed.

SQLiteObject methods

  • -(id) init – initialize a blank SQLiteObject
  • -(id) initWithPrimaryKey:(NSInteger)pk database:(sqlite3 *)db – initialize a new SQLiteObject with a primary key and database connection handle.
  • -(BOOL) isConnected – returns YES if the primary key and database connection handles are valid.

create and upgrading the schema

Creating the schema for the database is also an easy task once you get a new connection to the database.  When the application is first launched, the database does not exist.  Creating it is a three step process.

  1. Get the path to the database file and issue a call to sqlite3_open().  This initializes Sqlite in memory and creates a file in the  IOS apps documents folder.  When its first opened, it will have a zero length since there are no tables in this new database file.
  2. Using SQL, create the tables you need and for the purpose of this sample, we are inserting data as well using the SQL Insert and Create commands.
  3. close the database instance with a call to sqlite3_close().  This flushes the SQLite instance to the file, and there you go; one Sqlite database.

Upgrading the schema would follow the same procedures.  Open a connection to the database, then run the upgrade using SQL commands as you would on a normal SQL database.

retrieving data for viewing

Once the database has been populated with data, the application will attempt to load the data in the ViewControllers call to viewDidLoad.  To retrieve records from a SQLite database we need to use a sqlite3_stmt pointer.  To initialize a statement pointer, we issue a call to sqlite3_prepare().  The sqlite3_prepare() function takes 3 parameters that we care about.

  1. the database connection handle
  2. The SQL command string to issue against the database
  3. a statement object pointer to hold the retrieved query results.
- (void)viewDidLoad
{
    [super viewDidLoad];

    // setup a dummy table cell.  If we fail to load the database, you
    // will only see one record.
    _tableViewContents = [NSArray arrayWithObjects:@"item", nil];

    database = [SQLiteManager newConnection];

    if ( database )
    {
        // now we have opened the database, retrieve some records.
        sqlite3_stmt *statement = NULL;

        // execute the Sql statement
        int error = sqlite3_prepare_v2(database, "SELECT idx, firstname, lastname, phone FROM Contacts", -1, &statement, NULL);

        if (error == SQLITE_OK)
        {
            // got some results, now parse the records returned.
            NSMutableArray *results = [[NSMutableArray alloc] init];

            while (sqlite3_step(statement) == SQLITE_ROW) {
                // get the primary key
                int primaryKey = sqlite3_column_int(statement, 0);

                // get the data
                NSString *firstName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
                NSString *lastName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 2)];
                NSString *phone = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 3)];

                // insert into an object
                Person *contact = [[Person alloc] init];
                if (contact) {
                    contact.primaryKey = [NSNumber numberWithInt:primaryKey];
                    contact.firstName = firstName;
                    contact.lastName = lastName;
                    contact.phone = phone;

                    [results addObject:contact];
                }

            }
            // store the results for viewing in the tableview.
            _tableViewContents = results;
        }
        // clean up the SQL statement when your done.
        sqlite3_finalize(statement);
        statement = NULL;

        [SQLiteManager closeConnection:database];
    }
}

When extracting data from the results we use a sqlite3_step() function to loop through all the records returned. This function will continue to loop through all the records upon each subsequent call until you reach the end. Each record returned will have column data that is ordered in the same order as you would expect with the SQL Query that you issued against the database. Accessing each item in the record can be done with a calls to SQLite result set interface. The results are ordered by columns and there are multiple types of column calls, one method for each datatype supported by SQLite.
After you have finished retrieving all the records, you must remember to clean up the SQLite pointers or you will leak memory. To free the statement, issue a call to sqlite3_finalize() and this clears the statement instance and frees any allocated memory. Once that is done, you can close the database instance pointer if you need to.

source code & conclusion

Implementing Sqlite in your application is not that hard if you understand basic SQL database operations.  Using Sqlite within your applications is not hard at all, and this powerful library provides an easy way for developers to add database capabilities to their applications without a large library to support.  I have found SQLite to be very robust and works on a wide variety of platforms with very consistent results.

Source code for this article is available off GitHub here:  SQLiteExample.git

You can get more information on SQLite from their website http://www.sqlite.org


4 Comments

Building SQLite into your IOS applications


When I first started with IOS development, I used SQLite as the main database engine for my first iPhone application, AutoXLogger.  I recently started looking at the effort involved to revive this project and update it for IOS 7.0 and beyond. The version of SQLite that ships with Xcode is quite old and it lacks many of the newer features found in new builds. To get around this problem I created a static library that is built using the latest SQLite build.  It is really not too hard of a project once you get the proper build settings configured.  SQLite is very portable and it is not hard to build it on  IOS.

Building the library

To build a static library that you can use in your IOS applications is an easy task.

Create the library

step1 create IOS library project

Using Xcode, create a new static library for IOS.

Step2 name the project

Give the new project a name.

manipulate source code

Step3 delete default xcode files

Delete the default Xcode generated files. We will not be using these files.

Step4 Add SQLite source files

Add the SQLite source files.

configure build

SQLite offers a lot of build options that let you configure the performance and default settings built into the source code.  Some are helpful for tuning the database performance for the limitations of the mobile platform, but most of the time you won’t need to touch them.  You can view a full list of those options here: Compilation Options For SQLite.  Below are a  list of  options that I think might be useful on the mobile platforms

configure default values

  • SQLITE_DEFAULT_AUTOVACUUM=<0 or 1 or 2> Determine how the file size management and how free space is managed in the database file.  default is off(0).  See the documentation on the auto_vacuum flag for details on this feature.
  • SQLITE_DEFAULT_CACHE_SIZE=<pages>  This sets the default size of the page-cache for each attached database, in pages. This can be overridden by the PRAGMA cache_size command. The default value is 2000.

Operational control settings

  • SQLITE_SECURE_DELETE  This causes deleted content to be written overwritten with zeros.
  • SQLITE_THREADSAFE=<0 or 1 or 2>  Configures the threading model used bySQLite.
    • When compiled with SQLITE_THREADSAFE=0 all mutexing code is omitted and it is unsafe to use SQLite in a multithreaded program.
    • When compiled with SQLITE_THREADSAFE=1 SQLite can be used in a multithreaded environment. This is the default.
    • When compiled with SQLITE_THREADSAFE=2, SQLite can be used in a multithreaded program so long as no two threads attempt to use the same database connection (or any prepared statements derived from that database connection) at the same time.

    See the threading mode documentation for additional information on aspects of using SQLite in a multithreaded environment.

Enabling features

  • SQLITE_ENABLE_FTS4  When enabled, the string searching capabilities of the database engine are significantly enhanced.  This produces a performance gain when executing a query against the database, so enabling this feature is recommended.
Step5 enable SQLITE_ENABLE_FTS4

Enable the fast text searching by adding the SQLITE_ENABLE_FTS4 preprocessor flag

  • SQLITE_ENABLE_MEMORY_MANAGEMENT  This option allows SQLite to release unused memory upon request.

Analysis and Debugging Options

  • SQLITE_DEBUG  Turns on the debug asserts() used within SQLite.
  • SQLITE_MEMDEBUG  Turns on a debug memory allocator, similar to debug memory routines used in debug mode builds.

test the library

At this point you should have a static library building for your copy of SQLite ready to include in your Xcode project.   Up next we will write a test app to drive your new SQLite library.  In the mean time, if you want to try and build your own copy of this library, you can either download the SQLite source code yourself and follow these steps, or download the complete library project from my GitHub account.


Leave a comment

Fibonacci numbers


Recently while interviewing for new work, I keep getting asked the same interview question coding sample.

That is, write a function to do the Fibonacci number sequence. The last time I was asked to write a function to calculate the sequence.  This was a pleasant experience compared to writing it on a whiteboard.  So here it is, a view controller in Objective C that calculates the Fibonacci number sequence and pumps the output to NSLog().

//
//  ViewController.h
//  fib
//
//  Created by chris warner on 2/5/14.
//  Copyright (c) 2014 chris warner. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@end

 

//
//  ViewController.m
//  fib
//
//  Created by chris warner on 2/5/14.
//  Copyright (c) 2014 chris warner. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
-(NSNumber *) fibonacciWithInt:(unsigned int)iterator;
@end

@implementation ViewController

-(NSNumber *) fibonacciWithInt:(unsigned int)iterator
{
    NSNumber *returnValue  = [[NSNumber alloc] init];

    unsigned long seed1 = 1;  // f(n-1)
    unsigned long seed2 = 0;  // f(n-2)

    unsigned long fibonacci = 0;   // f(n)

    for (unsigned int n=0; n<=iterator; n++) {
        fibonacci = seed1 + seed2;

        // print the value of f(n), we skip F(0)
        if ( n > 0)
        {
            NSLog(@"%u: %lu", n, fibonacci);
        }

        // calculate f(n-1)
        seed1 = seed2;
        seed2 = fibonacci;
    }

    returnValue =  [NSNumber numberWithUnsignedLong:fibonacci];
    return returnValue;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSNumber *fibanocci = [self fibonacciWithInt:50];
    if (fibanocci != nil)
        NSLog(@"fibonacci value is:%@",[fibanocci stringValue]);
	// Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

I have been a software developer for a very long time now. Coding samples in interviews these days is an art of looking up the sample on the internet. So many people are asking this question that it is getting tiresome to answer over and over. In my past 3 interviews over the past year, I have been asked this question in each interview. As an interviewer you gain nothing from the experience because all a candidate needs to do is memorize the problem and recite the function on the whiteboard in an interview. Outside of their memorization skills, what have you learned about this potential candidate?

Do you know how well they can program, or how well they can memorize?

When I interview a potential candidate for a position, I rarely ask a coding question for just this reason.  If the person can intelligently and accurately answer technical questions that would imply an implicit knowledge of your companies primary coding language, then what is the point of the coding sample?

Follow

Get every new post delivered to your Inbox.

Join 203 other followers