Tuesday, January 31, 2012

Shake Animation Example

This example let you shake or animation your view on some event described.

Algorithm:

1.) Create a new project by File-> New -> Android Project name it ShakeAnimationExample.

2.) You will see some default code into your main.xml, strings.xml and android manifest file.

3.) Write following into main.xml file:






Read rest of entry

Email Intent Demo

This example will show you how to open email composer through your application.
Algorithm:
1.) Create a new project by File-> New -> Android Project name it EmailIntentDemo.
2.) You will see some default code into your main.xml, strings.xml and android manifest file.
3.) Now add 1 buttons into your main.xml or write following into main.xml file:
xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent" >
        android:text="Share" android:id="@+id/button1"
                android:layout_width="wrap_content" android:layout_height="wrap_content">>

>
4.) Your launcher activity EmailIntentDemo will have one default functions OnCreate().
5.) You must have to configure any email onto your device or simulator to get the output on this demo.
6.) To configure email goto applications and select “Email”, now follow the instructions given and configure your email onto device or simulator.
Steps:
1.) Create a project named EmailIntentDemo and set the information as stated in the image.
Build Target: Android 1.6
Application Name: EmailIntentDemo
Package Name: com.example. EmailIntentDemo
Activity Name: EmailIntentDemo
Min SDK Version: 4

2.) Open EmailIntentDemo.java file and write following code there:
package com.example.EmailIntentDemo; import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class EmailIntentDemo extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button shareButton = (Button) findViewById(R.id.button1);
        shareButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                        Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
                        emailIntent.setType("text/plain");
                        emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,"Email Intent Example");
                        emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "This is email is generated using EmailIntent Demo application to sow how we can directly compose a mail from our application.");
                        final PackageManager pm = getPackageManager();    
                        @SuppressWarnings("static-access")
                        final List<ResolveInfo> matches = pm.queryIntentActivities(emailIntent, pm.MATCH_DEFAULT_ONLY);    
                        ResolveInfo best = null;    
                        for (final ResolveInfo info : matches)
                        {
                                if (info.activityInfo.name.toLowerCase().contains("mail"))
                                        best = info;
                        }
                        if (best != null)
                        {
                                emailIntent.setClassName(best.activityInfo.packageName, best.activityInfo.name);
                                startActivity(emailIntent);
                        }
                }
        });
     
    }
}
3.) Compile and build the project.
4.) Run on 1.6 simulator for the output.




Read rest of entry

Monday, January 30, 2012

Simple Sqlite Database Interaction Using FMDB

Introduction

In the age where Core Data is king, the database that started it all is often overlooked. I’m talking of course about sqlite. As you may or may not know, prior to core data, sqlite was the preferred method of storing relational data on iOS devices.
Although, most developers don’t interact with sqlite directly, they still use it under the hood as the primary data store for core data. This is great and all, but there are often times when raw sqlite is still the preferred storage method.
A few of these might include:
  • Caching
  • Preferences
  • Simple objects
  • Portability
  • Cross platform applications
Recently, I have had to make heave use of raw sqlite as a caching strategy in a new project that I’m working on. Being that we are developing a framework for other developers to include in their projects, we can’t always assume that they have their environment set up to use core data. When I was but a n00b iOS developer I did all of the crazy sqlite management by hand. See This post series, but don’t spend too much time there because it’s embarrassing.
Gross right? Now, there is a much easier way to manage and interact with your sqlite databases. This library has been around for quite some time and I wish I had known about it earyly on.

FMDB

FMDB stands for Flying Meat Database. What a great name… This project aims to be a fully featured wrapper for sqlite.
You can clone their repository on their github.
This tutorial will give you a brief introduction to using FMDB to create a database, create a table, insert, fetch, and delete data.

Project Set Up

The first step is to download/clone fmdb from the url above. Once downloaded drag everything inside of the src folder into your project except fmdb.m. That file contains unit tests and a main, which will cause some conflicts in your project.
The next step is to link in the sqlite library. To do this:
  1. Click your project in the left column of XCode
  2. Click the main target in the middle column. In our case it’s “FMDBTest”
  3. Click the “Build Phases” tab in the third column
  4. Expand the arrow next to “Link Binary With Libraries”
  5. Click the “+” button
  6. Search for libsqlite3.0.dylib and double click it
When you are all done, it should look like this:
Screenshot
Now, that we have the library in place, let’s write some code.

Creating A Database

Obviously where you create your database is up to you, but we are going to do it in the appDelegate.
In addition to working with existing databases, fmdb can easily create any number of databases for you on the fly. After importing FMDatabase.h in our AppDelegate.m file, we can add the following code to the application:didFinishLaunching method.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *path = [docsPath stringByAppendingPathComponent:@"database.sqlite"];
 
FMDatabase *database = [FMDatabase databaseWithPath:path];
First, we resolve the path to the documents directory. Be careful, if you don’t need your database to be backed up, use the cache directory instead. When you send a path to the databaseWithPath method of fmdb, it first checks if the database exists, and if not, it creates it. Similarly, we could copy an existing database to the documents directory and source it the exact same way.

Opening The Database And Creating Tables

In order to perform any action on the database, it must first be opened. Here is the code to open the database and create a users table. Don’t worry about closing it right now, we will do that when we are all done.
[database open];
[database executeUpdate:@"create table user(name text primary key, age int)"];
Here we first call the open method of the database to open it. Next, we use the executeUpdate method to create the table. Make sure you use this method and not executeQuery when creating a table. This is a common error. The database should look like this after our update:
Screenshot
After we are all done here we close the database.

Inserting And Deleting Data

Inserting data using sqlite is very straight forward. You can either build your strings and pass them in directly OR use the sqlite format using “?’s” and letting fmdb do the work. Below is an example of each:
// Building the string ourself
NSString *query = [NSString stringWithFormat:@"insert into user values ('%@', %d)",
@"brandontreb", 25];
[database executeUpdate:query];
 
// Let fmdb do the work
[database executeUpdate:@"insert into user(name, age) values(?,?)",
@"cruffenach",[NSNumber numberWithInt:25],nil];
Generally, the second route is preferred as fmdb will do some of the sanitizing for your (such as add slashes to single quotes).
Now that we have some data in our database, let’s delete it. The following code will delete all users with an age of 25:
[database executeUpdate:@"delete from user where age = 25"];
And that should remove both of the records that we inserted.

Querying The Database

Querying the database is a bit more tricky than inserting and deleting. FMDB has some great utility methods for helping us out in certain circumstances, but for this tutorial, we will assume the don’t exist and show you how to fetch data out. If you are following along in a sample application, put this code before your delete code (so that we actually have some data to work with).
Below is an example of fetching all users from the database:
FMResultSet *results = [database executeQuery:@"select * from user"];
while([results next]) {
    NSString *name = [results stringForColumn:@"name"];
    NSInteger age  = [results intForColumn:@"age"];        
    NSLog(@"User: %@ - %d",name, age);
}
[database close];
We first query the database using the executeQuery method. This returns to us an FMResultsSet. Next we start a while loop that continues while there are results to be retrieved and fetch out each of our data points. Finally, we just print out each user.
And finally, our database gets close…

Conclusion

This concludes our sqlite using fmdb tutorial. As always, if you have any questions, please leave them here or write me on twitter.
You can download the source for this tutorial here
Read rest of entry

Making UITableViews look not so plain

As most of you probably know, UITableView’s are incredibly useful and versatile views to be using in your applications.
If you have ever tried to customize a UITableView though, you know that as soon as you start adding lots of UIViews, UILabels, and UImageViews to a cells ContentView, that these tableviews start to scroll slower and slower, and become choppier and choppier.
What we are going to explore today is how to remedy that situation.
To download the entire XCode project, you can find it at: http://github.com/elc/ICB_PrettyTableView
We are going to build a simple contact viewer, that will display the phones contacts. For each contact, if they have a first name, last name, email and phone number, they will be displayed within one cell, with different colors. The reason this is useful is because it provides the basics for customizing UITableViewCells that can really start to make your application look nice, and still scroll well.
If you don’t want to have simulated data inside the simulator, check out this post for copying data from your device to the simulator: How to import contacts into the iphone simulator
In this example, we have a standard UITableViewController. We are going to have a couple class variables defined in the header
#import 
#import 
 
@interface ICBTableViewController : UITableViewController
{
    ABAddressBookRef _addressBook;
}
 
@property (nonatomic, retain) NSArray *contacts;
 
@end
ABAddressBookRef _addressBook is defined in our header, so that we don’t have to release it until we dealloc. And the contacts is so that we can hold on to the data for our tableView.
In the main table view controller file we are going to override the – (void)viewDidLoad to provide some initial configuration of the tableView, as well as loading or generating our data. (We will generate fake data for devices or the simulator that don’t have address book data)
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.tableView.backgroundColor = UIColor.blackColor;
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
 
    ABAddressBookRef addressBook = ABAddressBookCreate();
    NSArray *tempArray = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
    tempArray = [tempArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        NSString *name1 = (NSString *)ABRecordCopyCompositeName((ABRecordRef)obj1);
        NSString *name2 = (NSString *)ABRecordCopyCompositeName((ABRecordRef)obj2);
        return [name1 compare:name2];
    }];
 
    if ([tempArray count] > 0) {
        self.contacts = tempArray;
    } else {
        NSMutableArray *tempMutableArray = [NSMutableArray arrayWithCapacity:100];
        for (int i = 0; i < 100; ++i) {
            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            if ((i % 9) != 0) {
                [dict setObject:[NSString stringWithFormat:@"FirstName%d", i] forKey:@"firstName"];
            }
            if ((i % 3) == 0) {
                [dict setObject:[NSString stringWithFormat:@"LastName%d", i] forKey:@"lastName"];
            }
            if ((i % 3) == 0 && (i % 2) == 0) {
                [dict setObject:[NSString stringWithFormat:@"emailTest%d@test%d.com", i, i] forKey:@"email"];
            }
            if ((i % 7) == 0) {
                NSString *string = [NSString stringWithFormat:@"%d", i];
                while ([string length] < 10) {
                    string = [string stringByAppendingFormat:@"%@", string];
                }
                [dict setObject:string forKey:@"phone"];
            }
            [tempMutableArray addObject:dict];
        }
        self.contacts = tempMutableArray;
    }
}
As you can see here we have a couple of self.tableView methods we have called to setup the background color, and also the cell separator style.
If you are running this application on a device, or simulator that has contacts, this method will also make a copy of the address book as the data to display. If there is no data in the address book, we create some fake test data just for displaying.
Also don’t forget to include our – (void)dealloc method for releasing our _addressBook variable.
- (void)dealloc
{
    CFRelease(_addressBook);
    [_contacts release];
    _contacts = nil;
}
We have to supply the tableView with our number of rows
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.contacts count];
}
The next portion we have to override is the – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath so that we can supply the tableView with our cells.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
 
    static NSString *CellIdentifier = @"ICBTableViewCellIdentifier";
 
    ICBTableViewCell *cell = (ICBTableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[ICBTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.textLabel.textColor = UIColor.whiteColor;
    }
    cell.tag = indexPath.row;
 
    NSObject *object = [self.contacts objectAtIndex:indexPath.row];
    if ([object isKindOfClass:NSDictionary.class]) {
        [cell setDictionary:(NSDictionary *)object];
    } else {
        [cell setRecord:(ABRecordRef)object];
    }
 
    return cell;
}
We are checking each object coming out of our array so that we can determine if we need to call the setDictionary, or setRecord method calls.
Now the meat of this tutorial, extending a UITableViewCell.
In our header we are going to define a bunch of strings that we want to display
#import 
#import 
 
@interface ICBTableViewCell : UITableViewCell
 
@property (nonatomic, retain) NSString *firstName;
@property (nonatomic, retain) NSString *lastName;
@property (nonatomic, retain) NSString *email;
@property (nonatomic, retain) NSString *phone;
@property (nonatomic, retain) NSString *address;
 
- (void)setRecord:(ABRecordRef)record;
- (void)setDictionary:(NSDictionary *)dict;
 
@end
And then our two set methods:
- (void)setRecord:(ABRecordRef)record
{
    self.firstName = [(NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty) autorelease];
    self.lastName = [(NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty) autorelease];
    self.email = [self getFirstEmail:record];
    self.phone = [self getFirstPhone:record];
    [self setNeedsDisplay];
}
 
- (void)setDictionary:(NSDictionary *)dict
{
    self.firstName = [dict objectForKey:@"firstName"];
    self.lastName = [dict objectForKey:@"lastName"];
    self.email = [dict objectForKey:@"email"];
    self.phone = [dict objectForKey:@"phone"];
    [self setNeedsDisplay];
}
Some tutorials will have you put this next part into a separate UIView subclass, and add that class as the contentView of this UITableViewCell, but I prefer to override the drawRect of the UITableViewCell, and do all my drawing there.
The first thing I am doing is getting the current graphics context so that we can draw to the screen, clipping to the rect that is passed in drawRect:(CGRect)rect, and then depending on whether this cell is even, I am filling the entire rect with an almost black color, or slightly lighter.
- (void)drawRect:(CGRect)rect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();
 
    CGContextClipToRect(ctx, rect);
    //If even
    if (((self.tag % 2) == 0)) {
        CGContextSetFillColorWithColor(ctx, [UIColor colorWithWhite:0.1f alpha:1.f].CGColor);
    } else {
        CGContextSetFillColorWithColor(ctx, [UIColor colorWithWhite:0.15f alpha:1.f].CGColor);
    }
 
    CGContextFillRect(ctx, rect);
The next thing I am going to figure out is whether I want this text to be centered in the cell, and I am determining this based off whether there is an email field or not.
//Vertically center our text, if no email
    BOOL isCentered = (self.email == nil);
And now for the meat of the drawRect method. We calculate the size of firstName, draw it offset from the left by 5, and then draw lastName right after it. We also change the color we are drawing between those two.
CGRect tempRect;
    CGFloat midY = CGRectGetMidY(rect);
    [[UIColor whiteColor] set];
    UIFont *defaultFont = [UIFont systemFontOfSize:16];
    CGSize size = [self.firstName sizeWithFont:defaultFont];
    if (isCentered == NO) {
        tempRect = CGRectMake(5, 0, size.width, size.height);
    } else {
        tempRect = CGRectMake(5, midY - size.height/2, size.width, size.height);
    }
    [self.firstName drawInRect:tempRect withFont:defaultFont];
 
    [[UIColor lightGrayColor] set];
    size = [self.lastName sizeWithFont:defaultFont];
    if (isCentered == NO) {
        tempRect = CGRectMake(CGRectGetMaxX(tempRect)+5, 0, size.width, size.height);
    } else {
        tempRect = CGRectMake(CGRectGetMaxX(tempRect)+5, midY - size.height/2, size.width, size.height);
    }
    [self.lastName drawInRect:tempRect withFont:defaultFont];
Next we find out if phone actually exists, and if so set the color to red, and draw it to the right of lastName. We also have to make sure we aren’t drawing this outside our boundaries, so we check to see where the end is, and if it is outside, we crop it to 5 pixels from the end.
if (self.phone != nil) {
        [[UIColor redColor] set];
        size = [self.phone sizeWithFont:defaultFont];
        CGFloat end = CGRectGetMaxX(tempRect) + size.width;
        if (end > rect.size.width) {
            size.width = CGRectGetMaxX(rect) - CGRectGetMaxX(tempRect) - 10; //-10 so that we get 5 from the end of last name, and 5 from the end of rect
        }
        if (isCentered == NO) {
            tempRect = CGRectMake(CGRectGetMaxX(rect) - size.width - 5, 0, size.width, size.height);
        } else {
            tempRect = CGRectMake(CGRectGetMaxX(rect) - size.width - 5, midY - size.height/2, size.width, size.height);
        }
        [self.phone drawInRect:tempRect withFont:defaultFont lineBreakMode:UILineBreakModeTailTruncation];
    }
And finally if our email actually exists draw it on the bottom left.
if (self.email != nil) {
        [[UIColor blueColor] set];
        size = [self.email sizeWithFont:defaultFont];
        tempRect = CGRectMake(5, midY, size.width, size.height);
        [self.email drawInRect:tempRect withFont:defaultFont];
    }
I hope this helps you in configuring UITableViewCells for your own project, and hopefully will let you start to think about the possibilities.
To download the entire XCode project, you can find it at: http://github.com/elc/ICB_PrettyTableView
Read rest of entry

ELCImageGrabber

As I was working on the ELCImagePickerController, bringing it up to speed for iOS 5, I needed to get some images inside my iOS simulator. I did some googling and came up with the handy method of dragging and dropping images onto the simulator and using Safari to save them to a photo album. This is all well and good for four or five photos, but it starts to really slow down after that. Also, if you ever run into a situation where you need to reset the simulator you’re stuck with doing it all over again. For the love of all that is automation, and of course any excuse to start new project in iOS 5, I knew it was time for a utility to handle this task for me.
With that, I give you ELCImageGrabber.

This was a quick project, so it’s not the prettiest interface, but it sure gets the job done. Tell it how many photos you want and watch as the previews go by and get stored in your photo library. The 64 images at a time limit is imposed by the Google image API for a single request, but there are plenty of ways around it. Also, I’ve hardcoded the search term in the source code, but perhaps you want rainbows and unicorns instead? I hope people find this useful and change it up to fit their needs as well. I’d love to see pull requests for any useful features that you lovely readers might add!
Get the code here!
Read rest of entry

Friday, December 23, 2011

Import contacts into the iPhone Simulator

If you’re working with AddressBook.framework chances are you’ll want to import your own data to test against when you’re in the simulator. Without being able to sync with iTunes or iCloud you may think you’re stuck entering in addresses manually; not only is that a huge pain, but there are probably lots of edge cases already in your address book you wouldn’t necessarily think of.

Fortunately there’s another option, with a tool called iPhone Backup Extractor. Download it, run it and click Read Backups (note that you’ll need to back up to iTunes, not iCloud). Select your device, and you should see a list of apps included in your backup. Choose the last item on the list, iOS Files, and extract it to your desktop. When it’s done take a look in the folder it created. You should find two files in the folder iOS Files/Library/AddressBook, AddressBook.sqlitedb and AddressBookImages.sqlitedb.

Next, open the simulator’s Application Support folder (in the Finder menu, choose Go -> Go to Folder…, enter ~/Library/Application Support/iPhone Simulator, and choose the SDK you’re working with) and drill down to Library/AddressBook. Quit the simulator if it’s open, delete everything in this directory, then copy the two files noted above from your backup. That’s it! If everything went well the next time you launch the simulator you should see all your contacts.

Pretty easy, really. If address book data is a major feature of your app, you might even want to have a few trusted beta testers send you their backups so you can test with their contacts. My experience is that there are a lot of unusual or invalid contacts floating around on people’s phones, and the more opportunity you have to test the better you’ll do once you release your app.
Read rest of entry

Making UITableViews look not so plain

As most of you probably know, UITableView’s are incredibly useful and versatile views to be using in your applications.
If you have ever tried to customize a UITableView though, you know that as soon as you start adding lots of UIViews, UILabels, and UImageViews to a cells ContentView, that these tableviews start to scroll slower and slower, and become choppier and choppier.
What we are going to explore today is how to remedy that situation.
To download the entire XCode project, you can find it at: http://github.com/elc/ICB_PrettyTableView
We are going to build a simple contact viewer, that will display the phones contacts. For each contact, if they have a first name, last name, email and phone number, they will be displayed within one cell, with different colors. The reason this is useful is because it provides the basics for customizing UITableViewCells that can really start to make your application look nice, and still scroll well.
If you don’t want to have simulated data inside the simulator, check out this post for copying data from your device to the simulator: How to import contacts into the iphone simulator
In this example, we have a standard UITableViewController. We are going to have a couple class variables defined in the header
#import 
#import 
 
@interface ICBTableViewController : UITableViewController
{
    ABAddressBookRef _addressBook;
}
 
@property (nonatomic, retain) NSArray *contacts;
 
@end
ABAddressBookRef _addressBook is defined in our header, so that we don’t have to release it until we dealloc. And the contacts is so that we can hold on to the data for our tableView.
In the main table view controller file we are going to override the – (void)viewDidLoad to provide some initial configuration of the tableView, as well as loading or generating our data. (We will generate fake data for devices or the simulator that don’t have address book data)
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.tableView.backgroundColor = UIColor.blackColor;
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
 
    ABAddressBookRef addressBook = ABAddressBookCreate();
    NSArray *tempArray = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
    tempArray = [tempArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        NSString *name1 = (NSString *)ABRecordCopyCompositeName((ABRecordRef)obj1);
        NSString *name2 = (NSString *)ABRecordCopyCompositeName((ABRecordRef)obj2);
        return [name1 compare:name2];
    }];
 
    if ([tempArray count] > 0) {
        self.contacts = tempArray;
    } else {
        NSMutableArray *tempMutableArray = [NSMutableArray arrayWithCapacity:100];
        for (int i = 0; i < 100; ++i) {
            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            if ((i % 9) != 0) {
                [dict setObject:[NSString stringWithFormat:@"FirstName%d", i] forKey:@"firstName"];
            }
            if ((i % 3) == 0) {
                [dict setObject:[NSString stringWithFormat:@"LastName%d", i] forKey:@"lastName"];
            }
            if ((i % 3) == 0 && (i % 2) == 0) {
                [dict setObject:[NSString stringWithFormat:@"emailTest%d@test%d.com", i, i] forKey:@"email"];
            }
            if ((i % 7) == 0) {
                NSString *string = [NSString stringWithFormat:@"%d", i];
                while ([string length] < 10) {
                    string = [string stringByAppendingFormat:@"%@", string];
                }
                [dict setObject:string forKey:@"phone"];
            }
            [tempMutableArray addObject:dict];
        }
        self.contacts = tempMutableArray;
    }
}
As you can see here we have a couple of self.tableView methods we have called to setup the background color, and also the cell separator style.
If you are running this application on a device, or simulator that has contacts, this method will also make a copy of the address book as the data to display. If there is no data in the address book, we create some fake test data just for displaying.
Also don’t forget to include our – (void)dealloc method for releasing our _addressBook variable.
- (void)dealloc
{
    CFRelease(_addressBook);
    [_contacts release];
    _contacts = nil;
}
We have to supply the tableView with our number of rows
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.contacts count];
}
The next portion we have to override is the – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath so that we can supply the tableView with our cells.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
 
    static NSString *CellIdentifier = @"ICBTableViewCellIdentifier";
 
    ICBTableViewCell *cell = (ICBTableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[ICBTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.textLabel.textColor = UIColor.whiteColor;
    }
    cell.tag = indexPath.row;
 
    NSObject *object = [self.contacts objectAtIndex:indexPath.row];
    if ([object isKindOfClass:NSDictionary.class]) {
        [cell setDictionary:(NSDictionary *)object];
    } else {
        [cell setRecord:(ABRecordRef)object];
    }
 
    return cell;
}
We are checking each object coming out of our array so that we can determine if we need to call the setDictionary, or setRecord method calls.
Now the meat of this tutorial, extending a UITableViewCell.
In our header we are going to define a bunch of strings that we want to display
#import 
#import 
 
@interface ICBTableViewCell : UITableViewCell
 
@property (nonatomic, retain) NSString *firstName;
@property (nonatomic, retain) NSString *lastName;
@property (nonatomic, retain) NSString *email;
@property (nonatomic, retain) NSString *phone;
@property (nonatomic, retain) NSString *address;
 
- (void)setRecord:(ABRecordRef)record;
- (void)setDictionary:(NSDictionary *)dict;
 
@end
And then our two set methods:
- (void)setRecord:(ABRecordRef)record
{
    self.firstName = [(NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty) autorelease];
    self.lastName = [(NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty) autorelease];
    self.email = [self getFirstEmail:record];
    self.phone = [self getFirstPhone:record];
    [self setNeedsDisplay];
}
 
- (void)setDictionary:(NSDictionary *)dict
{
    self.firstName = [dict objectForKey:@"firstName"];
    self.lastName = [dict objectForKey:@"lastName"];
    self.email = [dict objectForKey:@"email"];
    self.phone = [dict objectForKey:@"phone"];
    [self setNeedsDisplay];
}
Some tutorials will have you put this next part into a separate UIView subclass, and add that class as the contentView of this UITableViewCell, but I prefer to override the drawRect of the UITableViewCell, and do all my drawing there.
The first thing I am doing is getting the current graphics context so that we can draw to the screen, clipping to the rect that is passed in drawRect:(CGRect)rect, and then depending on whether this cell is even, I am filling the entire rect with an almost black color, or slightly lighter.
- (void)drawRect:(CGRect)rect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();
 
    CGContextClipToRect(ctx, rect);
    //If even
    if (((self.tag % 2) == 0)) {
        CGContextSetFillColorWithColor(ctx, [UIColor colorWithWhite:0.1f alpha:1.f].CGColor);
    } else {
        CGContextSetFillColorWithColor(ctx, [UIColor colorWithWhite:0.15f alpha:1.f].CGColor);
    }
 
    CGContextFillRect(ctx, rect);
The next thing I am going to figure out is whether I want this text to be centered in the cell, and I am determining this based off whether there is an email field or not.
//Vertically center our text, if no email
    BOOL isCentered = (self.email == nil);
And now for the meat of the drawRect method. We calculate the size of firstName, draw it offset from the left by 5, and then draw lastName right after it. We also change the color we are drawing between those two.
CGRect tempRect;
    CGFloat midY = CGRectGetMidY(rect);
    [[UIColor whiteColor] set];
    UIFont *defaultFont = [UIFont systemFontOfSize:16];
    CGSize size = [self.firstName sizeWithFont:defaultFont];
    if (isCentered == NO) {
        tempRect = CGRectMake(5, 0, size.width, size.height);
    } else {
        tempRect = CGRectMake(5, midY - size.height/2, size.width, size.height);
    }
    [self.firstName drawInRect:tempRect withFont:defaultFont];
 
    [[UIColor lightGrayColor] set];
    size = [self.lastName sizeWithFont:defaultFont];
    if (isCentered == NO) {
        tempRect = CGRectMake(CGRectGetMaxX(tempRect)+5, 0, size.width, size.height);
    } else {
        tempRect = CGRectMake(CGRectGetMaxX(tempRect)+5, midY - size.height/2, size.width, size.height);
    }
    [self.lastName drawInRect:tempRect withFont:defaultFont];
Next we find out if phone actually exists, and if so set the color to red, and draw it to the right of lastName. We also have to make sure we aren’t drawing this outside our boundaries, so we check to see where the end is, and if it is outside, we crop it to 5 pixels from the end.
if (self.phone != nil) {
        [[UIColor redColor] set];
        size = [self.phone sizeWithFont:defaultFont];
        CGFloat end = CGRectGetMaxX(tempRect) + size.width;
        if (end > rect.size.width) {
            size.width = CGRectGetMaxX(rect) - CGRectGetMaxX(tempRect) - 10; //-10 so that we get 5 from the end of last name, and 5 from the end of rect
        }
        if (isCentered == NO) {
            tempRect = CGRectMake(CGRectGetMaxX(rect) - size.width - 5, 0, size.width, size.height);
        } else {
            tempRect = CGRectMake(CGRectGetMaxX(rect) - size.width - 5, midY - size.height/2, size.width, size.height);
        }
        [self.phone drawInRect:tempRect withFont:defaultFont lineBreakMode:UILineBreakModeTailTruncation];
    }
And finally if our email actually exists draw it on the bottom left.
if (self.email != nil) {
        [[UIColor blueColor] set];
        size = [self.email sizeWithFont:defaultFont];
        tempRect = CGRectMake(5, midY, size.width, size.height);
        [self.email drawInRect:tempRect withFont:defaultFont];
    }
I hope this helps you in configuring UITableViewCells for your own project, and hopefully will let you start to think about the possibilities.
To download the entire XCode project, you can find it at: http://github.com/elc/ICB_PrettyTableView
Read rest of entry
 

sitemeter