Sharing SQLITE connection on iPhone threads may leave you hanging

June 17, 2010

iPhone SDK makes asynchronous operations really easy to use. There is no excuse for not making an application where the UI freezes whilst you’re downloading a URL or running a time-consuming SQL query. Here is an example of creating a background task (using NSInvocationOperation class) that you could call once the UI view has been initialized. In this example, the method init_data_details will be assigned its own thread and it will run in the background leaving the main thread for accepting user input. You’ll need to create a queue which here I’ve done in the Application Delegate class (essentially as a global variable that can be accessed from all views).

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSInvocationOperation *operation = 
    [[NSInvocationOperation alloc] 
        initWithTarget:self 
        selector:@selector(init_data_details) 
        object:nil];
[appDelegate.queue addOperation:operation];
[operation release];

In the init_data_details, I was running SQL queries on a local SQLITE3 database. To improve the performance of SQLITE, I was reusing a connection and all prepared statements. In case of memory warnings, I closed the connection and sqlite3_finalize all prepared statements. The problem was that I was sharing the same connection across multiple threads. This resulted in mysterious crashes with SQLITE3 stack traces that always ended up at sqlite3VdbeMemGrow. The fix in this case was to open a new connection (and prepare new statements) for all SQL accesses that were taking place in the background thread. Here is the outline of the operation:

- (void) init_data_details
{
// SQL is my encapsulation of the access to SQLITE3
// It creates a connection, handles open/close and 
// prepare statements

	SQL *sql2 = [[SQL alloc] init];
	
// pass this new connection to methods that need to access 
// the database in the background thread.

	NSMutableArray *data_array =
        [Someclass/object method  connection:sql2];

// process the data, update the UI, ...
// Here updating a UITableView object called
// overview_table

	[overview_table reloadData];

// Close connection, finialize prepare statements 
// for this connection, ...
	[sql2 close_connection];
	[sql2 release];
}

UIColor using RGB macro

May 30, 2010

The default OS X color picker does not show you the RGB color code. There are a number of other color pickers that you can install and they will extend the standard color picker giving you access to this information. I use the Rubicode’s RCWebColorPicker.

Once you’ve access to the RGB values you can use a C macro to define a shortcut for passing this RGB and getting a UIColor. Here I’ve defined two macros: RGB and AC_BLUE. The first takes three arguments and will yield a UIColor object. The AC_BLUE is an example of how you could use this macro to set the color palatte for your objective-C application.

You can define these macros in your project’s MyProject_Prefix.pch file so that they are available to all of the classes in your application.

#define RGB(r, g, b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]
#define AC_BLUE RGB(0x00, 0x95, 0xD2)

How to disable Flash on Safari

May 21, 2010

There is a very useful Safari plugin called ClickToFlash. It replaces all Adobe Flash content on a Web page with a placeholder and lets you selectively render the content. This means that by default Flash will not run, increasing the speed and satisfaction of browsing. If there is a piece of must see Flash content, then you can click on it to enable it. I know there are similar plugins on Firefox, but I was not aware of a Safari plugin for disabling Flash.

Aquacue Barnacle HD

May 21, 2010

Today we shipped the 1st ever Aquacue Barnacle capable of collecting data at 10 sec. intervals — a million times more frequent than your bi-monthly meter reads.

Aquacue turns any standard water meter into a smart meter in minutes. Aquacue’s system makes it simple to detect leaks, conserve water and reduce water bills.

Books on iPhone

May 10, 2010

I’ve recently started using my iPhone to read reference books. I bought a number of books on Amazon, but the Kindle app is kind of annoying for reference material. For example, there is no search, you cant jump to the Index section, the table of content is just a long list of long links making it difficult to scroll through the TOC pages. But there is a new class of reference material for the iPhone that take advantage of the native iPhone controls to provide a much more enjoyable and useful experience. By far the best such apps that I’ve seen to date are SDK IQ by cygen.com, 7-Steps to a successful Startup by Naeem Zafar, and Presenter Pro app.

MYSQL to SQLITE for iPhone

May 9, 2010

Today I had to migrate a MySQL table to SQLite so that I could use it in an iPhone app. The process is simple, you can export the MySQL table and then import it in SQLite. I found the following shell script in the MySQL site (I think), but the resulting file could not be imported in SQLite, since I had used the MySQL COMMENT to document each of the columns. SQLite does not understand column comments. So here is the updated script that makes the MYSQL dump work with SQLite.

#!/bin/sh 

/opt/local/lib/mysql5/bin/mysqldump --compact --compatible=ansi --default-character-set=binary -uUSERNAME -pPASSWORD DATABASE TABLE  | 
sed -e "s/COMMENT '.*',/,/" |
grep -v ' KEY "' | 
grep -v ' UNIQUE KEY "' | 
perl -e 'local $/;$_=<>;s/,\n\)/\n\)/gs;print "begin;\n";print;print "commit;\n"' | 
perl -pe ' 
if (/^(INSERT.+?)\(/) { 
$a=$1; 
s/\\'\''/'\'\''/g; 
s/\\n/\n/g; 
s/\),\(/\);\n$a\(/g; 
} 
' > db.sql 

You must substitute the USERNAME, PASSWORD, DATABASE and TABLE with the values for your project.

Next, you need to load this dump file into SQLite, issue the following command:

cat db.sql | sqlite3 db.db

This will create a SQLite database in a file called db.db. Now you can add the file db.db to your iPhone project, plus add the SQLite3 iphone framework and finally you’ll be ready to use the database from Objective-C.

UITableView in UIViewController

May 3, 2010

There are times when you want to add a UITableView to a UIViewController (without having to use a UITableViewController). To do this, you’ve to make sure to override the implementation of a number of methods in the delegate and data source classes to get the table to work as expected, i.e., to support deletion and insertion of rows. You’ve to remember to make the following changes:

You need to implement some of the methods of the UITableViewDelegate and UITableViewDataSource classes. Don’t forget to declare them in the interface definition. If you’re using the Interface Builder, make sure that you connect the table view to my_table. I forgot to do this step causing much frustration. If you forget this step, the table view object is not created, but calling methods on it don’t fail so you don’t have a easy null pointer exception to help you find the cause.
Read the rest of this entry »

How to tile an image using iPhone SDK

April 17, 2010

To tile an image on a UIImageView, you’ll need to use CGContextDrawTiledImage function. Here is a code snippet to tile an image called wave on the imageView object that you’ve defined.

- (void)viewDidLoad {
        [super viewDidLoad];
	
	UIImage *wave = [UIImage imageNamed:@"wave-bg.png"];
	CGSize imageViewSize = imageView.bounds.size;
	
	UIGraphicsBeginImageContext(imageViewSize);

	CGRect imageRect;
	imageRect.origin = CGPointMake(0.0, 0.0);
	imageRect.size = CGSizeMake(wave.size.width, wave.size.height);
	
	CGContextRef imageContext = UIGraphicsGetCurrentContext();
	CGContextDrawTiledImage(imageContext, imageRect, wave.CGImage);

	UIImage *finishedImage = UIGraphicsGetImageFromCurrentImageContext();
	
	UIGraphicsEndImageContext();
	
	imageView.image = finishedImage;
}

Sharing objects between view controllers

April 17, 2010

In an iPhone application where can you store the model (MVC) object and how do you share it between view controllers? There are a number of ways for doing this. I found the easiest way is to define the model object in the application delegate class and use the UIApplication sharedApplication singleton object from any view controller to access the model.

In your application delegate class define the model. Here the model is assumed to be an NSMutableArray object. Declare the model in the application delegate header file and the define it in the application delegate .m file.

...
@interface MyAppDelegate : NSObject <UIApplicationDelegate> 
{
	UIWindow *window;
        ...
	NSMutableArray *the_model;
}

@property (nonatomic, retain) NSMutableArray *the_model;
...
@end

Now you can access this model in any of your view controllers:

MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSMutableArray *model = appDelegate.the_model;

Web site graphs as art

April 3, 2010

Here is a fascinating application by Marcel Salathe that shows a web site as a very interesting graph. The graph to the left is the generated art for note19.com.

What do the colors mean?

blue is for links;
red for tables;
green for the DIV tag;
violet for images;
yellow for forms;
orange for line breaks and blockquotes;
blackfor the HTML tag, the root node; and
gray for all other tags.