Posts tagged ‘iPhone SDK’

Easy SQLite for the iPhone

Most applications need data, shockingly enough. I started working on my iPhone application in earnest a couple of years ago, before the availability of CoreData on the iPhone OS. The project is just now picking up some momentum, but I was pretty sure that I wanted to stay with SQLite on the device.

As it turns out, even though using SQLite with Objective-C is not too terribly complicated, I thought that there could have been a better way, and so I found Gus Mueller’s FMDB for iPhone page. He wrote an Objective-C wrapper around the SQLite calls that seems to work very well.

In order to use FMDB, you will still need to follow along with steps in other SQLite tutorials (such as this one) and do things like setting up your database file in Firefox SQLite Manager, copying the database file from the resources to the local file system on the device if needed in applicationDidFinishLaunching, and opening the database using the FMDB open method.

Once you have your database open, you can do nice things such as this:

	FMResultSet *rs = [db executeQuery:@"select * from companies where state = ?",
					   stateToSearchFor, nil];
	while ([rs next])
	{
		NSLog(@"Name: %@", [rs stringForColumn:@"companyname"];
	}

Just make sure that, if you want to hold your database open throughout the life cycle of your application (instead of opening and closing the database each time you read, write, or delete a record), make sure to use retain on the object returned by the FMDB open command, as the code returns an autorelease object. Or you could of course just modify the FMDB code.

Nicely formatted data to debugger console for iPhone SDK

I was looking to be able see the data in one of my SQLite3 database tables on the iPhone in the console, but could not find a nice and easy way to do this. Here is my solution to the problem.

This routine is set up to take in an NSMutableArray corresponding to the rows of the tabular data, and each of the elements of the array is an NSMutableArray of the columnar data. All of the items in the column array need to be of type NSString, and the first element of the rows array should be a row of column headers. If you need other types or do not want to use a headers row, please feel free to modify the code as you see fit.

Here is the NSLogTable header and implementation files that I put together for this purpose:

//
//  NSLogTable.h
//
 
#import <Foundation/Foundation.h>
 
@interface NSLogTable : NSObject {
 
}
 
+ (void)dumpTable:(NSMutableArray *)rows;
 
@end
//
//  NSLogTable.m
//
 
#import "NSLogTable.h"
 
@implementation NSLogTable
 
+ (void)dumpTable:(NSMutableArray *)rows
{
	int idx = 0;
	NSMutableArray *rowData;
	int colWidths[100];
	NSString *s;
	NSMutableString *ms = [[NSMutableString alloc] init];
	BOOL firstRow = YES;
 
	for (int i = 0; i < 100; i++) colWidths[i] = 0;
 
	// get the maximum column widths
	for (id row in rows)
	{
		rowData = (NSMutableArray *)row;
		for (int i = 0; i < [rowData count]; i++)
		{
			s = [rowData objectAtIndex:i];
			if ([s length] > colWidths[i])
			{
				colWidths[i] = [s length];
			}
		}
	}
 
	for (id row in rows)
	{
		[ms setString:@""];
		if (firstRow)
		{
			[ms appendString:@"     "];
			firstRow = NO;
		} else {
			[ms appendFormat:@"%4d ", idx];
		}		
 
		rowData = (NSMutableArray *)row;
		for (int i = 0; i < [rowData count]; i++)
		{
			s = [rowData objectAtIndex:i];
			[ms appendString:[s stringByPaddingToLength:colWidths[i] withString:@" " startingAtIndex:0]];
			[ms appendString:@" "];
		}
 
		NSLog(@"%@", ms);
		idx++;
	}
}
 
@end

Once you build your rows array (make sure to import the NSLogTable.h file into your implementation file), you send it to the console like this, where theData is your NSMutableArray:

[NSLogTable dumpTable:theData];

As always, please keep in mind that there is minimal optimization and error checking going on in this code. If you have any suggestions, please let me know.

The keys to the Kingdom

The biggest problem that I have had over the past 2 years or so of working with the iPhone SDK is the seemingly insurmountable learning curve to have you applications do something reasonably simple. I think this is partly due to my lack of any free time to dive into the whole iPhone SDK/Cocoa Touch/Objective-C world, and partly due to my straight ahead, VB6 development mentality.

For example, in my VB6 applications, if I need to display a dialog to the user to collect some bit of information, the parent code creates the form and shows it, and the child code closes down the child form when the user is done. This reasonably simple task has proven a bit elusive, as it seems like at times, I can’t get this to work for one reason or another.

Alas, I think I have finally figured out a good way to do this very task. Now, all I do in my parent view controller is to run the following code when I need to:

ChildViewController *controller = [[ChildViewController alloc]
					initWithNibName:@"ChildViewController" bundle:nil];
[self presentModalViewController:controller animated:YES];
[controller release];

In the new view that comes up by calling the code above, I use this code to get rid of the new view:

[[self parentViewController] dismissModalViewControllerAnimated:YES];

(Now of course, there is more going on here, as you need a way to pass values back and forth from one view to another. I think I might have a blog post from a few months ago to talk about this process.)

The end result is that I now have a simple way to show and dismiss forms in much the same way that I did with VB6. Does discovering this mean that I will continue to bumble around in the dark when it comes to the mysteries of inheriting from the correct classes in the iPhone SDK? Probably. Am I worried about it? Nope.

Oh, and I hope everyone has a nice Christmas (or insert your own holiday here, Kwanzaa, Festivus, Hanukkah, etc.), and drive safely out there. Grandma still hasn’t recovered after being run over by a reindeer.

Demo days (CONDG meeting, December 14, 2009)

The Central Ohio .NET Developers Group held their final meeting of the year last night at the Microsoft office in Polaris. Four people gave short demos of Xbox, Zune HD, Windows Mobile, and iPhone, and talked about developing for each platform.

The highlight of the evening was my name being drawn as winning the year’s final and perhaps most craptastic door prize, which I then gave to my coworker who was attending the meeting with me. He is into free t-shirts.

2009-12-15 09.13.18

Stanford iPhone App Programming lecture 18

Lecture 18 from the Stanford University iPhone Application Programming class was the class wrap-up lecture hosted by Evan Doll. He covered unit testing and localization on the iPhone platform, as well as answering some common iPhone SDK questions. The information he presented is somewhat relevant, especially with regards to the localization information, as the iPhone app store is becoming available in more countries.

Thanks to Evan and Alan and the crew, the videos were in general very informative and pertinent.

Oh, and Happy Halloween everyone!

Jamais Vu (CIDUG meeting, October 27, 2009)

Geoffrey Goetz gave a presentation on iPhone software development at the Columbus iPhone Developer User Group on October 27, 2009. He mostly talked about a lot of different topics, most importantly the creation of an iPhone application that utilized different types of view controllers.

During his demo, he created a new project from scratch based on the window template of the iPhone SDK, even though he was creating an application with a tab bar. I am probably going to revisit one of the applications that I am working on, which is also an application that uses a tab bar. However, I have had some issues with it, and I think that after seeing Geoffrey’s demo, it might be better to create it the way he did it than to use the tab bar application template included in the SDK.

Thanks to Geoffrey, he did a nice job (even though he ran way way over the time) and his information was super relevant.

Passing values and messages between views on iPhone

I am working on an iPhone application with some regular views and a table view, and I need to have the table view communicate with the main view. Seemingly a simple enough problem, but as I searched and searched, I could not find any concrete examples of how to do this, just a bunch of vague references about how views need to talk to each other and a larger number of folks suggesting the use of singletons.

Now, I have been known to use a global variable or two in my day, but in this instance, I figured I would dig a bit deeper.

As it turns out, the means to accomplish this for my task was easier than I thought. All that I did was to store a reference to the primary view controller in my secondary view controller, and that gave me access to any of the member variables in that class. In addition, this also gives me the ability to send messages to methods in that class.

So, in my primary view controller header file, we have the following:

#import <UIKit/UIKit.h>
 
@interface PassingValuesBetweenViewsViewController : UIViewController {
	IBOutlet UILabel *label;
	int selectedValue;
}
 
@property (nonatomic, retain) UILabel *label;
@property (nonatomic) int selectedValue;
 
- (IBAction)buttonWasTapped;
 
- (void)tableItemWasSelected:(int)itemSelected;
 
@end

And in the primary view controller implementation file:

#import "PassingValuesBetweenViewsViewController.h"
#import "SecondaryViewController.h"
 
@implementation PassingValuesBetweenViewsViewController
 
@synthesize label;
@synthesize selectedValue;
 
- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
 
	// Release any cached data, images, etc that aren't in use.
}
 
- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
}
 
- (void)dealloc {
    [super dealloc];
}
 
- (IBAction)buttonWasTapped
{
	SecondaryViewController *svc = [SecondaryViewController alloc];
	svc.vc = self;
	[self.view addSubview:svc.view];
}
 
- (void)tableItemWasSelected:(int)itemSelected
{
	NSLog(@"tableItemWasSelected called with %d", itemSelected);
	NSLog(@"The current value of selectedValue is %d", selectedValue);
	label.text = [NSString stringWithFormat: @"You selected #%d", itemSelected];
}
 
@end

The selectedValue member is an integer that gets updated in the table view with the selected cell, and the tableItemWasSelected methods is called from the table view when a cell is selected. In the buttonWasTapped method, the secondary view controller gets a reference to the primary view controller after it is allocated, and this enables the magic to happen.

Here is the secondary view controller header file:

#import <UIKit/UIKit.h>
 
#import "PassingValuesBetweenViewsViewController.h"
 
@interface SecondaryViewController : UITableViewController {
	PassingValuesBetweenViewsViewController *vc;
}
 
@property (nonatomic, retain) PassingValuesBetweenViewsViewController *vc;
 
@end

And the secondary view controller implementation file:

#import "SecondaryViewController.h"
 
@implementation SecondaryViewController
 
@synthesize vc;
 
- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
 
	// Release any cached data, images, etc that aren't in use.
}
 
- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
}
 
#pragma mark Table view methods
 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
 
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 50;
}
 
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
 
    // Set up the cell...
	cell.textLabel.text = [NSString stringWithFormat: @"Cell #%d", indexPath.row];
    return cell;
}
 
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
	vc.selectedValue = indexPath.row;
	[vc tableItemWasSelected:indexPath.row];
	[self.view removeFromSuperview];
}
 
- (void)dealloc {
    [super dealloc];
}
 
@end

As you can see here, the primary view controller is references from the didSelectRowAtIndexPath method, both in setting a member variable through standard dot notation, and in sending a message with a parameter to the primary view controller.

I have posted a copy of this code if you would like to download the entire project and work with it:

PassingValuesBetweenViews.zip

Please keep in mind this is not finished or production quality code.

Creating New Expressive Social Mediums on the iPhone

A guest lecture for the Stanford University iPhone Application Programming class called “Creating New Expressive Social Mediums on the iPhone” was hosted by Ge Wang on June 1, 2009. Professor Wang talked about some of his projects at Stanford and from Smule, including demos of Sonic Lighter, Ocarina, and Leaf Trombone.

I wish I had an iPhone instead of an iPod Touch so I could use Ocarina.

Stanford iPhone App Programming lecture 16

Lecture 16 from the Stanford University iPhone Application Programming class was hosted by Alan Cannistraro. He covered using the audio APIs, playing back video content, displaying web content in UIWebView controls, and he talked about settings on the iPhone platform.

The APIs and controls Alan demonstrated were very simple, and really meant for basic usage only, which is fine for most applications. He did talk about and demonstrate how to use a settings plist bundle so that an application’s preferences show up in the device’s Settings application, which was mildly interesting to me.

Optimizing OpenGL for iPhone

A guest lecture for the Stanford University iPhone Application Programming class called “Optimizing OpenGL for iPhone” was hosted by Tim Omernick of ngmoco on May 22, 2009. Tim covered a lot of his thoughts on, shockingly enough, optimizing OpenGL ES code on the iPhone platform.

Since my familiarity with OpenGL is null, most of what he talked about was over my head. I do have some game ideas, and once I get motivated to look into how OpenGL works, this presentation should be helpful. Also, the fireworks demo application he showed was very fun to play with.