<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lumenovis &#187; iPhone</title>
	<atom:link href="http://lumenovis.com/tag/iphone/feed/" rel="self" type="application/rss+xml" />
	<link>http://lumenovis.com</link>
	<description>Technology Consulting and Software Development</description>
	<lastBuildDate>Mon, 03 Jan 2011 18:13:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>First Responder Application</title>
		<link>http://lumenovis.com/2009/05/14/first-responder-application/</link>
		<comments>http://lumenovis.com/2009/05/14/first-responder-application/#comments</comments>
		<pubDate>Thu, 14 May 2009 20:43:07 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[first responder]]></category>

		<guid isPermaLink="false">http://lumenovis.com/?p=147</guid>
		<description><![CDATA[I recently worked with on an interesting application for first responders.  This app allows volunteer firemen (for example) to announce their location and availability with the click of a button upon receipt of an alarm.  Their peers and leaders can then see updated location and response information in near realtime, allowing for more effective decision [...]]]></description>
			<content:encoded><![CDATA[<p>I recently worked with on an interesting application for first responders.  This app allows volunteer firemen (for example) to announce their location and availability with the click of a button upon receipt of an alarm.  Their peers and leaders can then see updated location and response information in near realtime, allowing for more effective decision making.  The app makes heavy use of REST polling and messaging plus mapping via Google Maps and has hooks for realtime communications.</p>
<p><a href="http://lumenovis.com/wp-content/uploads/2009/06/screenshot-20090512-082048.png"><img class="alignnone size-medium wp-image-148" title="screenshot-20090512-082048" src="http://lumenovis.com/wp-content/uploads/2009/06/screenshot-20090512-082048-200x300.png" alt="" width="200" height="300" /></a> <a href="http://lumenovis.com/wp-content/uploads/2009/06/screenshot-20090512-082107.png"><img class="alignnone size-medium wp-image-149" title="screenshot-20090512-082107" src="http://lumenovis.com/wp-content/uploads/2009/06/screenshot-20090512-082107-200x300.png" alt="" width="200" height="300" /></a> <a href="http://lumenovis.com/wp-content/uploads/2009/06/screenshot-20090512-082130.png"><img class="alignnone size-medium wp-image-150" title="screenshot-20090512-082130" src="http://lumenovis.com/wp-content/uploads/2009/06/screenshot-20090512-082130-200x300.png" alt="" width="200" height="300" /></a> <a href="http://lumenovis.com/wp-content/uploads/2009/06/screenshot-20090512-082137.png"><img class="alignnone size-medium wp-image-151" title="screenshot-20090512-082137" src="http://lumenovis.com/wp-content/uploads/2009/06/screenshot-20090512-082137-200x300.png" alt="" width="200" height="300" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://lumenovis.com/2009/05/14/first-responder-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>KiddyBase 1.0</title>
		<link>http://lumenovis.com/2009/03/23/kiddybase-10/</link>
		<comments>http://lumenovis.com/2009/03/23/kiddybase-10/#comments</comments>
		<pubDate>Mon, 23 Mar 2009 17:40:34 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[kiddybase]]></category>

		<guid isPermaLink="false">http://lumenovis.com/?p=136</guid>
		<description><![CDATA[I just wrapped up version 1 of KiddyBase, the electronic baby book for iPhone. The idea came to me after watching my wife agonize to remember what the kids had said or done over the past week/month. I looked around and found a few height/weight trackers, but no comprehensive journal to track the baby&#8217;s milestones. [...]]]></description>
			<content:encoded><![CDATA[<p>I just wrapped up version 1 of KiddyBase, the electronic baby book for iPhone.  The idea came to me after watching my wife agonize to remember what the kids had said or done over the past week/month.  I looked around and found a few height/weight trackers, but no comprehensive journal to track the baby&#8217;s milestones.  Thus was KiddyBase born.</p>
<p>You can read more about the app in the product section.  Here are some additional screenshots:<br />
<a href="http://lumenovis.com/wp-content/uploads/2009/03/screenshot-20090318-223550.jpg"><img class="alignnone size-medium wp-image-127" title="screenshot-20090318-223550" src="http://lumenovis.com/wp-content/uploads/2009/03/screenshot-20090318-223550-200x300.jpg" alt="" width="200" height="300" /></a> <img class="alignnone size-medium wp-image-143" title="screenshot-20090624-125858" src="http://lumenovis.com/wp-content/uploads/2009/06/screenshot-20090624-125858-200x300.png" alt="" width="200" height="300" /> <a href="http://lumenovis.com/wp-content/uploads/2009/03/screenshot-20090318-224140.jpg"><img class="alignnone size-medium wp-image-138" title="screenshot-20090318-224140" src="http://lumenovis.com/wp-content/uploads/2009/03/screenshot-20090318-224140-200x300.jpg" alt="" width="200" height="300" /></a> <a href="http://lumenovis.com/wp-content/uploads/2009/03/screenshot-20090318-224211.jpg"><img class="alignnone size-medium wp-image-139" title="screenshot-20090318-224211" src="http://lumenovis.com/wp-content/uploads/2009/03/screenshot-20090318-224211-200x300.jpg" alt="" width="200" height="300" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://lumenovis.com/2009/03/23/kiddybase-10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Conversion Application</title>
		<link>http://lumenovis.com/2009/02/25/iphone-conversion-application/</link>
		<comments>http://lumenovis.com/2009/02/25/iphone-conversion-application/#comments</comments>
		<pubDate>Wed, 25 Feb 2009 18:14:47 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://lumenovis.com/?p=88</guid>
		<description><![CDATA[I was recently contracted to develop a conversion application for the iPhone called &#8220;All in One Converter&#8221;, with a focus on business users. This was a fun project in that: I chose to develop a generalized XML processing engine that would allow the creation and deployment of new conversion sets on the fly. we developed [...]]]></description>
			<content:encoded><![CDATA[<p>I was recently contracted to develop a conversion application for the iPhone called &#8220;All in One Converter&#8221;, with a focus on business users.  This was a fun project in that:</p>
<ol>
<li> I chose to develop a generalized XML processing engine that would allow the creation and deployment of new conversion sets on the fly.</li>
<li> we developed a proxy server to feed currency updates</li>
<li> I developed a full calculator stack that runs inline with the converter</li>
<li> I created a flexible &#8220;favorites&#8221; or bookmarking mechanism</li>
<li> we &#8220;invented&#8221; the Zone Scheduler, which helps schedule meeting across time zones</li>
</ol>
<p>Attached are some screenshots.  Should be in the iTunes store shortly.</p>
<div id="attachment_91" class="wp-caption alignnone" style="width: 210px"><a href="http://lumenovis.com/wp-content/uploads/2009/02/screenshot-20090225-112027.png"><img class="size-medium wp-image-91" title="screenshot-20090225-112027" src="http://lumenovis.com/wp-content/uploads/2009/02/screenshot-20090225-112027-200x300.png" alt="Conversion View" width="200" height="300" /></a><p class="wp-caption-text">Conversion View</p></div>
<div id="attachment_92" class="wp-caption alignnone" style="width: 210px"><a href="http://lumenovis.com/wp-content/uploads/2009/02/screenshot-20090225-112033.png"><img class="size-medium wp-image-92" title="screenshot-20090225-112033" src="http://lumenovis.com/wp-content/uploads/2009/02/screenshot-20090225-112033-200x300.png" alt="Calculator View" width="200" height="300" /></a><p class="wp-caption-text">Calculator View</p></div>
<div id="attachment_93" class="wp-caption alignnone" style="width: 210px"><a href="http://lumenovis.com/wp-content/uploads/2009/02/screenshot-20090225-112143.png"><img class="size-medium wp-image-93" title="screenshot-20090225-112143" src="http://lumenovis.com/wp-content/uploads/2009/02/screenshot-20090225-112143-200x300.png" alt="Currency View" width="200" height="300" /></a><p class="wp-caption-text">Currency View</p></div>
<div id="attachment_94" class="wp-caption alignnone" style="width: 210px"><a href="http://lumenovis.com/wp-content/uploads/2009/02/screenshot-20090225-112253.png"><img class="size-medium wp-image-94" title="screenshot-20090225-112253" src="http://lumenovis.com/wp-content/uploads/2009/02/screenshot-20090225-112253-200x300.png" alt="Zone Scheduler View" width="200" height="300" /></a><p class="wp-caption-text">Zone Scheduler View</p></div>
]]></content:encoded>
			<wfw:commentRss>http://lumenovis.com/2009/02/25/iphone-conversion-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Directory Search Application</title>
		<link>http://lumenovis.com/2009/02/10/iphone-directory-search-application/</link>
		<comments>http://lumenovis.com/2009/02/10/iphone-directory-search-application/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 20:36:58 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://lumenovis.com/?p=98</guid>
		<description><![CDATA[I just finished a contract app called &#8220;BizFinder&#8221; that searches a set of business directories based on the location of the user. This app required extensive XML processing and a number of REST operations, integration with Google Maps (both remote server and local app), and use of the onboard GPS capability. This is version 1- [...]]]></description>
			<content:encoded><![CDATA[<p>I just finished a contract app called &#8220;BizFinder&#8221; that searches a set of business directories based on the location of the user.  This app required extensive XML processing and a number of REST operations, integration with Google Maps (both remote server and local app), and use of the onboard GPS capability.</p>
<p>This is version 1- version 2 will have a host of new features and user friendly options.</p>
<p>Here are some screen shots (more to follow):</p>
<div id="attachment_114" class="wp-caption alignnone" style="width: 210px"><a href="http://lumenovis.com/wp-content/uploads/2009/02/screenshot-20090225-113209.png"><img class="size-medium wp-image-114" title="screenshot-20090225-113209" src="http://lumenovis.com/wp-content/uploads/2009/02/screenshot-20090225-113209-200x300.png" alt="Search Page" width="200" height="300" /></a><p class="wp-caption-text">Search Page</p></div>
]]></content:encoded>
			<wfw:commentRss>http://lumenovis.com/2009/02/10/iphone-directory-search-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code Snippet &#8211; iPhone SqlLite DBO</title>
		<link>http://lumenovis.com/2009/01/20/code-snippet-iphone-sqllite-dbo/</link>
		<comments>http://lumenovis.com/2009/01/20/code-snippet-iphone-sqllite-dbo/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 17:05:07 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[DBO]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[Sqlite]]></category>

		<guid isPermaLink="false">http://lumenovis.com/?p=84</guid>
		<description><![CDATA[I&#8217;ve been developing database applications for years and I&#8217;ve welcomed the advances in abstraction that have allowed me to focus more on value-added business logic and less on low-level database access routines (with associated pitfalls). So it was a jarring &#8220;back to the past&#8221; slap in the face when I started developing on the iPhone [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been developing database applications for years and I&#8217;ve welcomed the advances in abstraction that have allowed me to focus more on value-added business logic and less on low-level database access routines (with associated pitfalls).  So it was a jarring &#8220;back to the past&#8221; slap in the face when I started developing on the iPhone and Sqlite&#8230; once again, we (the developers) are required to manage all of the details of the database and write all of the plumbing required to marshall data to and from the database.</p>
<p>I looked for an ORM solution and found EntropyDB and SQLitePersistentObjects&#8230; the former requires a license for use in commercial applications, and the latter was quite immature when I first looked at it (though it appears to have move forward significantly and is worth another look).  While it would be challenging and fun to develop a &#8220;Hibernate for iPhone&#8221;, I simply didn&#8217;t have the time, but I figured I could leverage the &#8220;80/20&#8243; rule and get most of the benefit with minimal effort.  So I created a couple of base classes that, with minimal custom configuration, make any Objective C object into a &#8220;pseudo-DBO&#8221;.  Here&#8217;s the source- use it as you see fit.  (Note: This is an early version and has not been exhaustively tested, so keep that in mind.  And yes, I know there is a great deal that could be done with Protocols and other Objective C capabilities that would significantly improve this concept&#8230; this is something that&#8217;s grown organically and I hope to someday get around to cleaning it up.)</p>
<p>Basically- extend DatabaseObject in any object you want to have persisted, implement the &#8220;abstract&#8221; methods, and start using it.  Pretty straight forward.</p>
<p>Here&#8217;s an example of usage:<br />
&#8212;&#8212;<br />
Workout* workout = [[Workout alloc] init];<br />
workout.name = @&#8221;Workout 1&#8243;;<br />
workout.notes = @&#8221;some desc&#8221;;<br />
workout.startTime = [NSDate date];<br />
[workout persist];<br />
[[DBWrapper getInstance] databaseDump];</p>
<p>Workout* w2 = [Workout findById:workout.localId];<br />
NSInteger res = [Workout countAll];<br />
NSArray* res2 = [Workout findWhere:@"name = \"Medium workout\""];<br />
&#8212;-</p>
<p>DatabaseObject.h<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>#import<br />
#import</p>
<p>@interface DatabaseObject : NSObject {<br />
NSInteger localId;<br />
NSDate* createdDate;<br />
NSDate* modifiedDate;<br />
BOOL isDirty;<br />
}</p>
<p>// abstract methods<br />
+ (NSString*) generateCreateSql;<br />
+ (NSString*) getTableName;<br />
- (NSString*) generateInsertSql;<br />
- (NSString*) generateUpdateSql;<br />
- (NSString*) generateDeleteSql;<br />
+ (id) constructDboFromResults:(sqlite3_stmt*)stmt;<br />
+ (void) test;</p>
<p>// props<br />
@property (readwrite) NSInteger localId;<br />
@property (readwrite) BOOL isDirty;<br />
@property (readwrite, retain) NSDate* createdDate;<br />
@property (readwrite, retain) NSDate* modifiedDate;</p>
<p>// methods<br />
+ (void) createTable:(BOOL)dropFirst;<br />
- (void) persist;<br />
- (void) unpersist;<br />
+ (id) findById:(NSInteger)id;<br />
+ (NSArray*) findAll;<br />
+ (NSArray*) findWhere:(NSString*)where;<br />
+ (NSInteger) countAll;<br />
+ (NSInteger) countWhere:(NSString*)where;</p>
<p>@end</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>DatabaseObject.m<br />
&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
#import &#8220;DatabaseObject.h&#8221;<br />
#import &#8220;DBWrapper.h&#8221;</p>
<p>@interface DatabaseObject()<br />
+ (int) executeSql:(NSString*)sql;<br />
+ (void) executeQuery:(sqlite3_stmt*)stmt sql:(NSString*)sql;<br />
@end</p>
<p>@implementation DatabaseObject<br />
@synthesize localId, isDirty, createdDate, modifiedDate;</p>
<p>- (id) init<br />
{<br />
[super init];<br />
self.localId = -1;<br />
self.createdDate = nil;<br />
self.modifiedDate = nil;<br />
return self;<br />
}</p>
<p>- (void) dealloc<br />
{<br />
self.localId = -1;<br />
self.createdDate = nil;<br />
self.modifiedDate = nil;<br />
[super dealloc];<br />
}</p>
<p>+ (void) createTable:(BOOL)dropFirst<br />
{<br />
NSLog(@&#8221;DatabaseObject::createTable %@&#8221;, [self getTableName]);<br />
NSMutableString* sql = nil;<br />
if (dropFirst) {<br />
NSLog(@&#8221;dropping table&#8221;);<br />
sql = [[NSMutableString alloc] init];<br />
[sql appendString:@"DROP TABLE \""];<br />
[sql appendString:[self getTableName]];<br />
[sql appendString:@"\""];<br />
@try{<br />
[DatabaseObject executeSql:sql];<br />
}<br />
@catch (NSException* e) {<br />
NSLog(@&#8221;Exception caught dropping table: %@&#8221;, e);<br />
}<br />
}</p>
<p>sql = [self generateCreateSql];<br />
[DatabaseObject executeSql:sql];</p>
<p>}</p>
<p>- (void) persist<br />
{<br />
NSLog(@&#8221;DatabaseObject::persist&#8221;);<br />
if (self.localId &lt; 0) {<br />
NSLog(@&#8221;insert&#8221;);<br />
self.createdDate = [NSDate date];<br />
self.modifiedDate = [NSDate date];</p>
<p>NSString *sql = [self generateInsertSql];<br />
self.localId = [DatabaseObject executeSql:sql];<br />
} else {<br />
NSLog(@&#8221;update&#8221;);<br />
self.modifiedDate = [NSDate date];</p>
<p>NSString *sql = [self generateUpdateSql];<br />
[DatabaseObject executeSql:sql];<br />
}<br />
}</p>
<p>- (void) unpersist<br />
{<br />
NSLog(@&#8221;DatabaseObject::unpersist&#8221;);<br />
NSString* sql = [self generateDeleteSql];<br />
[DatabaseObject executeSql:sql];</p>
<p>}</p>
<p>+ (id) findById:(NSInteger)id<br />
{<br />
NSLog(@&#8221;DatabaseObject::findById %d&#8221;, id);<br />
NSString* sql = [[NSString alloc] initWithFormat:@&#8221;SELECT * FROM %@ WHERE id=%i&#8221;, [self getTableName], id];<br />
sqlite3_stmt* stmt = nil;<br />
if(sqlite3_prepare_v2([[DBWrapper getInstance] database], [sql UTF8String], -1, &amp;stmt, NULL) != SQLITE_OK) {<br />
[NSException raise:@"DatabaseException" format:@"Error while creating statement. '%s'", sqlite3_errmsg([[DBWrapper getInstance] database])];<br />
}<br />
if (sqlite3_step(stmt) == SQLITE_ROW) {<br />
return [self constructDboFromResults:stmt];<br />
}<br />
else<br />
{<br />
return  nil;<br />
}<br />
}</p>
<p>+ (NSArray*) findAll<br />
{<br />
NSLog(@&#8221;DatabaseObject::findAll&#8221;);<br />
NSString* sql = [[NSString alloc] initWithFormat:@&#8221;SELECT * FROM %@&#8221;, [self getTableName]];<br />
sqlite3_stmt* stmt = nil;<br />
if(sqlite3_prepare_v2([[DBWrapper getInstance] database], [sql UTF8String], -1, &amp;stmt, NULL) != SQLITE_OK) {<br />
[NSException raise:@"DatabaseException" format:@"Error while creating statement. '%s'", sqlite3_errmsg([[DBWrapper getInstance] database])];<br />
}<br />
NSMutableArray* res = [[NSMutableArray alloc] init];<br />
while (sqlite3_step(stmt) == SQLITE_ROW) {<br />
[res addObject:[self constructDboFromResults:stmt]];<br />
}<br />
return res;<br />
}</p>
<p>+ (NSArray*) findWhere:(NSString*)where<br />
{<br />
NSLog(@&#8221;DatabaseObject::findWhere %@&#8221;, where);<br />
NSString* sql = [[NSString alloc] initWithFormat:@&#8221;SELECT * FROM %@ WHERE %@&#8221;, [self getTableName], where];<br />
sqlite3_stmt* stmt = nil;<br />
if(sqlite3_prepare_v2([[DBWrapper getInstance] database], [sql UTF8String], -1, &amp;stmt, NULL) != SQLITE_OK) {<br />
[NSException raise:@"DatabaseException" format:@"Error while creating statement. '%s'", sqlite3_errmsg([[DBWrapper getInstance] database])];<br />
}<br />
NSMutableArray* res = [[NSMutableArray alloc] init];<br />
while (sqlite3_step(stmt) == SQLITE_ROW) {<br />
[res addObject:[self constructDboFromResults:stmt]];<br />
}<br />
return res;<br />
}</p>
<p>+ (NSInteger) countAll<br />
{<br />
NSLog(@&#8221;DatabaseObject::countAll&#8221;);<br />
return [self countWhere:@"1"];<br />
}</p>
<p>+ (NSInteger) countWhere:(NSString*)where<br />
{<br />
NSLog(@&#8221;DatabaseObject::countWhere %@&#8221;, where);<br />
NSString* sql = [[NSString alloc] initWithFormat:@&#8221;SELECT COUNT(*) FROM %@ WHERE %@&#8221;,[self getTableName], where];<br />
sqlite3_stmt *stmt;<br />
if (sqlite3_prepare_v2([[DBWrapper getInstance] database], [sql UTF8String], -1, &amp;stmt, NULL) != SQLITE_OK) {<br />
[NSException raise:@"DatabaseException" format:@"Error while creating statement. '%s'", sqlite3_errmsg([[DBWrapper getInstance] database])];<br />
}</p>
<p>if (sqlite3_step(stmt) == SQLITE_ROW) {<br />
NSInteger res = sqlite3_column_int(stmt, 0);<br />
NSLog(@&#8221;DatabaseObject::countWhere returning %d&#8221;, res);<br />
return res;<br />
}<br />
else<br />
{<br />
NSLog(@&#8221;DatabaseObject::countWhere: could not get count err=%s for sql %@&#8221;, sqlite3_errmsg([[DBWrapper getInstance] database]), sql);<br />
}<br />
return -1;</p>
<p>}</p>
<p>#pragma mark utils<br />
+ (int) executeSql:(NSString*)sql<br />
{<br />
NSLog(@&#8221;DBWrapper::executeSql: executing %@&#8221;, sql);<br />
sqlite3_stmt* stmt = nil;<br />
if(sqlite3_prepare_v2([[DBWrapper getInstance] database], [sql UTF8String], -1, &amp;stmt, NULL) != SQLITE_OK) {<br />
[NSException raise:@"DatabaseException" format:@"Error while creating statement. '%s'", sqlite3_errmsg([[DBWrapper getInstance] database])];<br />
}</p>
<p>if (SQLITE_DONE != sqlite3_step(stmt)) {<br />
NSLog(@&#8221;DBWrapper::executeSql: sql failed; %s&#8221;, sqlite3_errmsg([[DBWrapper getInstance] database]));</p>
<p>//Reset the add statement.<br />
sqlite3_reset(stmt);</p>
<p>[NSException raise:@"DatabaseException" format:@"Error while executing sql statement. '%s'", sqlite3_errmsg([[DBWrapper getInstance] database])];<br />
}<br />
else<br />
{<br />
NSLog(@&#8221;DBWrapper::executeSql: success&#8221;);</p>
<p>//Reset the add statement.<br />
sqlite3_reset(stmt);</p>
<p>return sqlite3_last_insert_rowid([[DBWrapper getInstance] database]);<br />
}<br />
return -1;<br />
}</p>
<p>+ (void) executeQuery:(sqlite3_stmt*)stmt sql:(NSString*)sql<br />
{<br />
NSLog(@&#8221;DBWrapper::executeQuery: executing %@&#8221;, sql);<br />
if(sqlite3_prepare_v2([[DBWrapper getInstance] database], [sql UTF8String], -1, &amp;stmt, NULL) != SQLITE_OK) {<br />
[NSException raise:@"DatabaseException" format:@"Error while creating statement. '%s'", sqlite3_errmsg([[DBWrapper getInstance] database])];<br />
}</p>
<p>}</p>
<p>@end<br />
&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>DBWrapper.h<br />
&#8212;&#8212;&#8212;&#8212;&#8211;<br />
#import<br />
#import</p>
<p>@interface DBWrapper : NSObject {<br />
sqlite3* database;<br />
}</p>
<p>+(DBWrapper*) getInstance;</p>
<p>- (BOOL) openDatabase;<br />
- (void) closeDatabase;<br />
- (void) databaseDump;<br />
- (NSString*) nsStringFromResult:(sqlite3_stmt*)res column:(unsigned)col;</p>
<p>- (void) setDatabase:(sqlite3*)db;<br />
- (sqlite3*) database;</p>
<p>@end<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>DBWrapper.m<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
#import &#8220;DBWrapper.h&#8221;</p>
<p>@interface DBWrapper()<br />
- (NSString *) getDBPath;<br />
- (void) createDatabaseIfNeeded;<br />
@end</p>
<p>@implementation DBWrapper</p>
<p>- (void) setDatabase:(sqlite3*)db {<br />
database = db;<br />
}</p>
<p>- (sqlite3*) database {<br />
return database;<br />
}</p>
<p>static DBWrapper *INSTANCE = nil;</p>
<p>+ (DBWrapper *)getInstance<br />
{<br />
//	@synchronized(self)<br />
//	{<br />
if (!INSTANCE) {<br />
INSTANCE = [[[DBWrapper alloc] init] retain];<br />
}<br />
return INSTANCE;<br />
//	}<br />
//	return nil;<br />
}</p>
<p>- (BOOL) openDatabase {<br />
NSLog(@&#8221;opening database&#8221;);<br />
[self createDatabaseIfNeeded];<br />
if (sqlite3_open([[self getDBPath] UTF8String], &amp;database) == SQLITE_OK) {<br />
NSLog(@&#8221;database open&#8221;);<br />
sqlite3_extended_result_codes(database, 1);<br />
return YES;<br />
}<br />
else {<br />
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.<br />
return NO;<br />
}<br />
}</p>
<p>- (void) closeDatabase {<br />
NSLog(@&#8221;closing database&#8221;);<br />
if(database) {<br />
sqlite3_close(database);<br />
}<br />
}</p>
<p>#pragma mark utils</p>
<p>- (NSString *) getDBPath {</p>
<p>//Search for standard documents using NSSearchPathForDirectoriesInDomains<br />
//First Param = Searching the documents directory<br />
//Second Param = Searching the Users directory and not the System<br />
//Expand any tildes and identify home directories.<br />
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);<br />
NSString *documentsDir = [paths objectAtIndex:0];<br />
return [documentsDir stringByAppendingPathComponent:@"com.lumenova.workouttracker.sqlite"];<br />
}</p>
<p>- (void) createDatabaseIfNeeded {</p>
<p>//Using NSFileManager we can perform many file system operations.<br />
NSFileManager *fileManager = [NSFileManager defaultManager];<br />
NSError *error;<br />
NSString *dbPath = [self getDBPath];<br />
BOOL success = [fileManager fileExistsAtPath:dbPath];</p>
<p>if(!success) {<br />
success = [fileManager createFileAtPath:dbPath contents:[NSData data] attributes:nil ];<br />
if (!success)<br />
NSAssert1(0, @&#8221;Failed to create writable database file with message &#8216;%@&#8217;.&#8221;, [error localizedDescription]);<br />
}<br />
}</p>
<p>- (NSString*) nsStringFromResult:(sqlite3_stmt*)res column:(unsigned)col {<br />
char* string = (char *)sqlite3_column_text(res, col);<br />
if (string == NULL) {<br />
return nil;<br />
} else {<br />
return [NSString stringWithUTF8String:string];<br />
}<br />
}</p>
<p>- (void) databaseDump {<br />
NSLog(@&#8221;databaseDump&#8221;);<br />
sqlite3_stmt* stmt = nil;<br />
NSString* sql = @&#8221;SELECT name FROM sqlite_master WHERE type=&#8217;table&#8217; ORDER BY name&#8221;;<br />
if(sqlite3_prepare_v2(database, [sql UTF8String], -1, &amp;stmt, NULL) != SQLITE_OK) {<br />
NSAssert1(0, @&#8221;Error while creating statement. &#8216;%s&#8217;&#8221;, sqlite3_errmsg(database));<br />
}</p>
<p>while (sqlite3_step(stmt) == SQLITE_ROW) {<br />
NSString* tableName = [self nsStringFromResult:stmt column:0];<br />
NSLog(@&#8221;TABLE: %@&#8221;, tableName);</p>
<p>sqlite3_stmt* stmt2 = nil;<br />
NSString* sql2 = [[[NSString alloc] initWithFormat: @&#8221;SELECT * FROM %@&#8221;, tableName] autorelease];<br />
if(sqlite3_prepare_v2(database, [sql2 UTF8String], -1, &amp;stmt2, NULL) != SQLITE_OK) {<br />
NSAssert1(0, @&#8221;Error while creating statement. &#8216;%s&#8217;&#8221;, sqlite3_errmsg(database));<br />
}<br />
int cols = sqlite3_column_count(stmt2);<br />
for (int i = 0; i &lt; cols; i++) {<br />
// can get names here with sqlite3_column_name<br />
}</p>
<p>while (sqlite3_step(stmt2) == SQLITE_ROW) {<br />
NSMutableString* sb = [[[NSMutableString alloc] init] autorelease];<br />
[sb appendString:@"  row:"];<br />
for (int i = 0; i &lt; cols; i++) {<br />
NSString* ret = [self nsStringFromResult:stmt2 column:i];<br />
if (ret == nil) {<br />
[sb appendString:@"NULL"];<br />
} else {<br />
[sb appendString: ret];<br />
}<br />
if (i &lt; (cols &#8211; 1)) {<br />
[sb appendString:@", "];<br />
}<br />
}<br />
NSLog(sb);<br />
}</p>
<p>}</p>
<p>}</p>
<p>@end<br />
&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>Example of a class the extends the DBO:<br />
&#8212;&#8212;&#8212;&#8212;&#8212;<br />
#import &#8220;StrengthSet.h&#8221;<br />
#import &#8220;DBWrapper.h&#8221;</p>
<p>@implementation StrengthSet<br />
@synthesize exerciseId, reps, weight, notes, hint;</p>
<p>- (id) init<br />
{<br />
[super init];<br />
self.reps = 0;<br />
self.weight = 0.0;<br />
self.notes = nil;<br />
self.exerciseId = -1;<br />
self.hint = MAINTAIN;<br />
return self;<br />
}</p>
<p>- (void) dealloc<br />
{<br />
self.notes = nil;<br />
[super dealloc];<br />
}</p>
<p>#pragma mark DBO methods<br />
+(NSString*) getTableName {<br />
return @&#8221;strength_set&#8221;;<br />
}</p>
<p>+ (NSString*) generateCreateSql<br />
{<br />
NSMutableString* sql = [[NSMutableString alloc] initWithFormat:@&#8221;CREATE TABLE \&#8221;%@\&#8221; (&#8220;, [StrengthSet getTableName]];<br />
// DBO<br />
[sql appendString:@"\"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \"created_date\" INTEGER NOT NULL, \"modified_date\" INTEGER NOT NULL"];<br />
[sql appendString:@", "];<br />
// Exercise<br />
[sql appendString:@"\"exercise_id\" INTEGER NOT NULL, \"reps\" INTEGER NOT NULL, \"weight\" REAL NOT NULL, \"hint\" INTEGER NOT NULL, \"notes\" TEXT"];<br />
[sql appendString:@")"];<br />
return sql;<br />
}</p>
<p>- (NSString*) generateInsertSql<br />
{<br />
NSInteger now = [[NSDate date] timeIntervalSince1970];<br />
NSString* sql = [[[NSString alloc] initWithFormat:@&#8221;INSERT INTO %@ (created_date, modified_date, exercise_id, reps, weight, hint, notes) VALUES (%i, %i, %i, %i, %f, %i, \&#8221;%@\&#8221;)&#8221;,<br />
[StrengthSet getTableName],<br />
now,<br />
now,<br />
self.exerciseId,<br />
self.reps,<br />
self.weight,<br />
self.hint,<br />
self.notes ] autorelease];<br />
return sql;<br />
}</p>
<p>- (NSString*) generateUpdateSql<br />
{<br />
NSInteger now = [[NSDate date] timeIntervalSince1970];<br />
NSMutableString* sql = [[NSMutableString alloc] initWithFormat:@&#8221;UPDATE %@ SET modified_date=%d, exercise_id=%d, reps=%d, weight=%f, hint=%d, notes=\&#8217;%@\&#8217;&#8221;,<br />
[StrengthSet getTableName],<br />
now,<br />
self.exerciseId,<br />
self.reps,<br />
self.weight,<br />
self.hint,<br />
self.notes];<br />
[sql appendFormat:@" WHERE id=%d", self.localId];</p>
<p>return sql;</p>
<p>}</p>
<p>- (NSString*) generateDeleteSql<br />
{<br />
return [[NSString alloc] initWithFormat:@&#8221;DELETE FROM %@ WHERE id=%i&#8221;, [StrengthSet getTableName], self.localId];<br />
}</p>
<p>+ (id) constructDboFromResults:(sqlite3_stmt*)stmt<br />
{<br />
NSLog(@&#8221;StrengthExercise::constructDboFromResults&#8221;);</p>
<p>StrengthSet* result = [[[StrengthSet alloc] init] autorelease];<br />
result.localId = sqlite3_column_int(stmt, 0);<br />
result.createdDate = [NSDate dateWithTimeIntervalSince1970:sqlite3_column_int(stmt, 1)];<br />
result.modifiedDate = [NSDate dateWithTimeIntervalSince1970:sqlite3_column_int(stmt, 2)];<br />
result.exerciseId = sqlite3_column_int(stmt, 3);<br />
result.reps = sqlite3_column_int(stmt, 4);<br />
result.weight = sqlite3_column_double(stmt, 5);<br />
result.hint = sqlite3_column_int(stmt, 6);<br />
result.notes = [[DBWrapper getInstance] nsStringFromResult:stmt column:7];</p>
<p>return result;</p>
<p>}</p>
<p>@end<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
]]></content:encoded>
			<wfw:commentRss>http://lumenovis.com/2009/01/20/code-snippet-iphone-sqllite-dbo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

