Welcome to my iphone development code blog

Welcome to my iphone development code blog
"SIMPLICITY IS BEST PROFESSION"

Thursday, July 15, 2010

Linkedin Themes

Seriously loved the themes module of linkedin iphone app

just a little logic and theme module is made.....

we can use the same for all over the project




just using uipicker make one view that just shows this color schemes

and take its value



and pass it to backcolor of below tiles .... simple

remember prepare images as vector images and only white.... with transpeent bkg......




Enjoy!

New Report style era of iphone

New Style of iphone reports are really awesome and cool

for big agencies and cmd level apps can now have such good reports

what you say about this???






I really loved this

How to access camera or gallery of device iphone/ipod

I've been working on a number of iPhone camera applications. The default photograph functionality seemed kind of awkward to me, and I wanted to have a much simpler process and interface. This is an example of an Xcode project which shows how to load the camera interface with a custom overlaid image, and then wait for a tap anywhere on the screen to take a photo.



To start, I created a new project (a View-based application) called CameraTapper.



I knew I would need to subclass UIImagePickerController, but there's really not much I needed to over-ride. I created a new file (with UIView as a base) called CustomCamera.m (and .h) and then modified them to support the "tap anywhere to capture" functionality:



CustomCamera.h



#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

@
interface CustomCamera : UIImagePickerController {

}

@
end


CustomCamera.m



#import "CustomCamera.h"


@
implementation CustomCamera

-
(void) dealloc {
[super dealloc];

}

-
(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

// override the touches ended method
// so tapping the screen will take a picture
[self takePicture];
}

-
(void)viewDidDisappear:(BOOL)animated {

[super viewDidDisappear:animated];
}

-
(void) viewDidAppear: (BOOL)animated {

[super viewDidAppear:animated];
}

@
end



I also added an overlay to the project (a 24 bit transparent png):




This overlay would give the user the visual clue of what to do in order to progress to the next step.


The rest of the code is simply there to demonstrate how this could be implemented in another project. I made a simple button within the CameraTapperViewController.m file to load the CustomCamera view, and I added functionality to show how the "taken" photograph could be used after it had been taken -- by adding it to the background of the main view itself.


CameraTapperViewController.h


#import


@interface CameraTapperViewController : UIViewController
{
UIImageView *myImageView;
UIImage *myImage;

}

@end



CameraTapperViewController.m


#import "CameraTapperViewController.h"
#import "CustomCamera.h"


@implementation CameraTapperViewController

- (void) launchCamera {

// Set up the camera

CustomCamera *cameraController = [[CustomCamera alloc] init];
cameraController.sourceType =
UIImagePickerControllerSourceTypeCamera;
cameraController.delegate = self;

cameraController.showsCameraControls = NO;
cameraController.navigationBarHidden = YES;
cameraController.toolbarHidden = YES;

// overlay on top of camera lens view

UIImageView *cameraOverlayView = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:@"camera_overlay.png"]];
cameraOverlayView.alpha = 0.0f;
cameraController.cameraOverlayView = cameraOverlayView;

// animate the fade in after the shutter opens

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelay:2.2f];
cameraOverlayView.alpha = 1.0f;
[UIView commitAnimations];

[cameraOverlayView release];

[self presentModalViewController:cameraController animated:YES];

}

// User took an image
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingImage:(UIImage *)inImage

editingInfo:(NSDictionary *)editingInfo {
myImage = inImage;
myImageView.image = myImage;

// Get rid of the picker interface

[[picker parentViewController]
dismissModalViewControllerAnimated:YES];
[picker release];

}

- (void)viewDidLoad {

// display the background image view
myImageView = [[UIImageView alloc]
initWithFrame:CGRectMake(0, 0, 320, 480)];
[self.view addSubview:myImageView];

// display the button to launch the camera

UIButton *btnLaunchCamera = [UIButton

buttonWithType

:UIButtonTypeRoundedRect];
btnLaunchCamera.frame = CGRectMake(60, 220, 200, 40);
[btnLaunchCamera setTitle:@"Launch Camera" forState:

UIControlStateNormal];
[btnLaunchCamera addTarget:self action:@selector(launchCamera) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:btnLaunchCamera];

[super viewDidLoad];

}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];

}

- (void)viewDidUnload {
}

- (void)dealloc {

[myImageView release];
[super dealloc];
}

@end



For further exploration, I'd like to start playing with taking a real-time (or near real-time) feed of images and manipulating them -- similar to some of the augmented reality applications that are currently being developed...

How to make settings in iphone

Settings of your application are managed by iphone itself

Step 1: Create a Sample Application

I have used an application similar to the one created in the tutorial presented here (IPhone SDK Hello World).

Step 2: Create a Settings Bundle


Create a new File Command + N and then select Settings from the side menu and Settings  Bundle. The file must be named Settings.bundle to work correctly. 










This will create two new files Root.strings and Root.plist. Open the Root.plist file and you should see the following screen listing some sample settings. This is actually a graphical representation of an XML file which defines the settings and how they are displayed. (You can see the xml code by right clicking the file and selecting Open as Plain Text)




Step 3: Define Settings Schema


The Root element has three child elements (1) Title; which defines the title of this settings view and is set to the name of the application. (2) StringTable; which is not covered in this tutorial. (3) PreferenceSpecifiers which contains all the settings we wish to elicit from the user. PreferenceSpecifiers has type Array and has a child element of type Dictionary for each setting: Item 1, item2 and so forth. We can add items by selecting PreferenceSpecifiers and clicking the Grey button at the end of the row.

Each setting has several properties of type string including the common required properties; Title and Type (Note all strings are case sensitive). The title defines the label displayed beside the control used to modify the setting and type defines the type of control used. There are seven possible controls which can be selected using the Type property:


PSGroupSpecifier

This is the simplest control and has only the two properties defined described above. It is used as a separator to break-up groups of similar settings. It cannot accept any input from the user.


PSTitleValueSpecifier

This displays a "Read Only" setting it cannot accept input from the user but can be used to display settings changed elsewhere.


Key:

This is a String property which can be set to any text, the text is used as a key to map to the value that a user will enter into the control.  


DefaultValue:

Another String property which can store any text, this defines the Text that will be displayed in the specifier.



PSTextFieldSpecifier

The next type of control is the TextField, it has some additional properties which are listed below


Key:

This is a String property which can be set to any text, the text is used as a key to map to the value that a user will enter into the text field.  


DefaultValue:

Another String property which can store any text this defines the initial Text that will be entered into the TextField when it is first loaded.



IsSecure

This is a boolean property which defines if the charecters of the text field will be hidden, set to enabled for password fields.


KeyboardType

A String property which can have one of the following values: Alphabet, NumbersAndPunctuati on, NumberPad, URL, EmailAddress. This property specifies which type of keyboard to display when text field is selected


AutocapitalizationType

A String property which can have one of the following values: None, Sentences, Words, AllCharacters


AutoCorrectionType

A String property which can have one of the following values: Default, No, Yes
 
 

PSSliderSpecifier

This displays a slider on a bar which allows the user to select a number in a specified range. In addition to the standard Title and Type specifiers the Slider has the following properties.

Key:

This is a String property which can be set to any text, the text is used as a key to map to the value that a user will enter into the control.  

MinimumValue

A property storing a numerical value which corresponds to the slider being on the left end of the bar.

MaximumValue

A property storing a numerical value which corresponds to the slider being on the right end of the bar.

DefaultValue:

 A numerical  property which defines the original position of the slider. 



PSToggleSwitchSpecifier


Displays a toggle switch which can be either On or Off.

Key:

This is a String property which can be set to any text, the text is used as a key to map to the value that a user will enter into the control. 

TrueValue:

A boolean property which defines the value of the control of the toggle button is in the On position.

FalseValue:

A boolean property which defines the value of the control of the toggle button is in the Off position.

DefaultValue:

A boolean property which defines the position of the Toggle button the first time it is loaded.




PSMultiValueSpecifier

Multi-Value Specifier
Displays a list in a second view and allows the user to select one element from the list.

Key:

This is a String property which can be set to any text, the text is used as a key to map to the value that a user will enter into the control. 


Values:

A property of type Array which stores sub-elements of type String, each element provides a a pos sible value for the control to take. 


Titles:

A property of type array which stores sub-elements of type String, each element provides a textual representation of one of the values specified in the previous property. For example if the first element of the values array is "01" and the first element of the titles array is "January" then the user is shown January but if January is selected the value stored for the control is 01.  

DefaultValue:

Another String property that defines the initial value of the control, should be one of the elements of the Values list.

PSChildPaneSpecifier  

 

Key:

This is a String property which can be set to any text, the text is used as a key to map to the value that a user will enter into the control. 

File:

The name of another plist file without the extension.


Step 4: Retrieving Values of Settings

You can retrieve the value of a setting by using the command given below; Replace the hilighted text with the name of the setting you want to get the value of. 

NSString* settingValue = [[NSUserDefaults standardUserDefaults] stringForKey:@"<Setting Key>"]



Step 5: Loading a Child Pane


The final of the Seven Controls allows you to add a sub view. The procedure to do so is to add a new file Command + N and select Other from the menu on the right Property List from the list of fle types.

Create a child prefernces schema exactly as you created the original schema.

No in the original schema add a PSChildPaneSpecifier and add a File item to the specifier with the file name of the child view (less the extension).

Technically this should be enough but as you will see if you run your code now the child view will not load. To load your child view the child plist file has to be inside the settings bundle but I can't find a way of doing this from within XCode (after half an our of random tinkering). So just open a terminal and move the file into the bundle manually. To do this browse to the directory containing your xcode project, and find child.plist file (or whatever you named it). Use mv child.plist Settings.bundle/child.plist to move your file and then click Build and Go in XCode.

If there is some way of moving files into the bundle through XCode that you know of please leave a coment and I will update this document.

Make db layer apart from code

Some times we need to do a big project in xcode
we should try to make datacotroller deferent than our codes

make a data controller


@interface DataController : NSObject {
NSMutableArray *list;
NSMutableArray *namelist;
NSMutableArray *mobiles;
NSMutableData *tdata;
NSMutableArray *ids;
NSMutableArray *sgns;
NSMutableArray *Emails;
NSMutableArray *Fexs;
NSMutableArray *Birthdays;
NSMutableArray *Annidays;
NSString *searchfilter;
}

- (unsigned)countOfList;
-(NSMutableArray *) GetList;
-(NSMutableArray *) GetIds;
-(NSMutableArray *) Getsgns;
-(NSMutableArray *) Getmobiles;
-(NSMutableArray *) GetEmails;
-(NSMutableArray *) GetFexs;
-(NSMutableArray *) GetBirthdays;
-(NSMutableArray *) GetAnniversarydays;
-(void) SetFilter:(NSString *)search;
-(NSString *)searchfilter;
- (void)createDemoData:(NSString *)search;
@end

and implement it as data layer



#import "DataController.h"
#import "DataSet.h"
#import "WebServiceHelper.h"

@interface DataController ()
@property (nonatomic, copy, readwrite) NSMutableArray *list;
@property (nonatomic, copy, readwrite) NSMutableArray *namelist;
@property (nonatomic, copy, readwrite) NSMutableArray *ids;
@property (nonatomic, copy, readwrite) NSMutableArray *sgns;
@property (nonatomic, copy, readwrite) NSMutableArray *Emails;
@property (nonatomic, copy, readwrite) NSMutableArray *Fexs;
@property (nonatomic, copy, readwrite) NSMutableArray *mobiles;
@property (nonatomic, copy, readwrite) NSMutableArray *Birthdays;
@property (nonatomic, copy, readwrite) NSMutableArray *Annidays;
@property (nonatomic, copy, readwrite) NSString *searchfilter;
- (void)createDemoData:(NSString *)search;
@end

@implementation DataController

@synthesize list;
@synthesize namelist;
@synthesize ids,Annidays;
@synthesize sgns,mobiles,Emails,Fexs,Birthdays;
@synthesize searchfilter;


- (id)init {
if (self = [super init]) {
searchfilter = [[NSString alloc] init];

}
return self;
}

- (void)setList:(NSMutableArray *)newList {
if (list != newList) {
[list release];
list = [newList mutableCopy];
}
}

- (unsigned)countOfList {
return [list count];
}

-(void)SetFilter:(NSString *)search
{
searchfilter=search;
[self createDemoData:searchfilter];
}

- (void)dealloc {

[searchfilter release];
[ids release];
[namelist release];
[list release];
[super dealloc];
}


- (void)createDemoData:(NSString *)search
{

WebServiceHelper *DataCon = [[WebServiceHelper alloc] init];


DataCon.XMLNameSpace = @"http://tempuri.org/";
DataCon.XMLURLAddress = @"http://urdomain.com/webservicefolder/service1.asmx";
DataCon.MethodName = @"MyMethodName";
DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
[DataCon.MethodParameters setObject:[[NSUserDefaults standardUserDefaults] stringForKey:@"name_preference"] forKey:@"UserName"];
[DataCon.MethodParameters setObject:[[NSUserDefaults standardUserDefaults] stringForKey:@"password_preference"] forKey:@"Password"];
[DataCon.MethodParameters setObject:search forKey:@"GroupId"];
tdata = [DataCon initiateConnection];

DataSet *dsMyDataSet = [[DataSet alloc] initWithXMLData:tdata];

NSMutableArray *Name = [[NSMutableDictionary alloc] init];
NSMutableArray *ID = [[NSMutableDictionary alloc] init];
NSMutableArray *SGN = [[NSMutableDictionary alloc]init];
NSMutableArray *mob = [[NSMutableDictionary alloc]init];
NSMutableArray *mobarr = [[NSMutableArray alloc] init];
NSMutableArray *em = [[NSMutableDictionary alloc]init];
NSMutableArray *emarr = [[NSMutableArray alloc]init];
NSMutableArray *fe = [[NSMutableDictionary alloc]init];
NSMutableArray *fearr = [[NSMutableArray alloc]init];
NSMutableArray *bd = [[NSMutableDictionary alloc]init];
NSMutableArray *bdarr = [[NSMutableArray alloc]init];
NSMutableArray *an = [[NSMutableDictionary alloc]init];
NSMutableArray *anarr = [[NSMutableArray alloc]init];

ID = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"Id"];
Name = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"DisplayName"];
SGN = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"SubGroupName"];
mob = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"DisplayPhone"];
em = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"DisplayEmail"];
fe = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"DisplayFax"];
bd = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"Birthday"];
an = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"Anniversary"];


NSEnumerator *mobIterator= [mob objectEnumerator];
NSString *mobnm;

while(mobnm = [mobIterator nextObject])
{

if([mobnm isEqualToString:@"@#$%"])
{
[mobarr addObject:@""];
}
else
{
[mobarr addObject:mobnm];
}

}

NSEnumerator *emIterator= [em objectEnumerator];
NSString *emnm;


while(emnm = [emIterator nextObject])
{
if([emnm isEqualToString:@"@#$%"])
{
[emarr addObject:@""];
}
else
{
[emarr addObject:[NSString stringWithString:emnm]];
}
}
NSEnumerator *feIterator= [fe objectEnumerator];
NSString *fenm;

while(fenm = [feIterator nextObject])
{

if([fenm isEqualToString:@"@#$%"])
{
[fearr addObject:@""];
}
else
{
[fearr addObject:fenm];
}

}

NSEnumerator *dateIterator= [bd objectEnumerator];
NSString *datestring;

while(datestring = [dateIterator nextObject])
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss-'06:00'"];
NSDate *date = [dateFormatter dateFromString:datestring];
[dateFormatter setDateFormat:@"dd MMM "];
if(date==nil)
{
}
else {
[bdarr addObject:[dateFormatter stringFromDate:date]];

}
}

NSEnumerator *anIterator= [an objectEnumerator];
NSString *anstring;

while(anstring = [anIterator nextObject])
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss-'06:00'"];
NSDate *date = [dateFormatter dateFromString:anstring];
[dateFormatter setDateFormat:@"dd MMM "];
if(date==nil)
{
}
else {
[anarr addObject:[dateFormatter stringFromDate:date]];

}
}

self.namelist = Name;
self.list = playList;
self.ids = ID;
self.sgns = SGN;
self.mobiles = mobarr;
self.Emails = emarr;
self.Fexs = fearr;
self.Birthdays = bdarr;
self.Annidays = anarr;

[an release];
[anarr release];
[SGN release];
[ID release];
[Name release];

[emarr release];
[em release];
[mob release];
[mobarr release];
[fearr release];
[fe release];
[bd release];
[bdarr release];
}



-(NSMutableArray *) GetList
{
return self.namelist;
}
-(NSMutableArray *) GetIds
{
return self.ids;
}
-(NSMutableArray *) Getsgns
{
return self.sgns;
}
-(NSMutableArray *) Getmobiles
{
return self.mobiles;
}
-(NSMutableArray *) GetEmails
{
return self.Emails;
}
-(NSMutableArray *) GetFexs
{
return self.Fexs;
}
-(NSMutableArray *) GetBirthdays
{
return self.Birthdays;
}
-(NSMutableArray *) GetAnniversarydays
{
return self.Annidays;
}
@end

now you are following good structure in xcode ...

Enjoy!!

how to read and write to plist

we can use the code below

- (void)readPlist
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
NSString *documentsDirectory = [paths objectAtIndex:0]; //2

NSString *path = [documentsDirectory stringByAppendingPathComponent:@"Contacts.plist"];
listOfItems = [[NSMutableArray alloc] initWithContentsOfFile:path];

}

- (void)writeToPlist
{

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
NSString *documentsDirectory = [paths objectAtIndex:0]; //2
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"Contacts.plist"];

[listOfItems writeToFile:path atomically:YES];

}

search functions

here are some useful search functions

- (void) searchbarTextDidBeginEditing:(UISearchBar *)theSearchBar {
searchbar.showsCancelButton = YES;

if(ovController == nil)
ovController = [[OverlayViewController alloc] initWithNibName:@"OverlayView" bundle:[NSBundle mainBundle]];

CGFloat yaxis = self.navigationController.navigationBar.frame.size.height;
CGFloat width = self.view.frame.size.width;
CGFloat height = self.view.frame.size.height;
CGRect frame = CGRectMake(0, yaxis, width, height);
ovController.view.frame = frame;
ovController.view.backgroundColor = [UIColor grayColor];
ovController.view.alpha = 0.5;

ovController.rvController = self;

[self.tableview insertSubview:ovController.view aboveSubview:self.parentViewController.view];

searching = YES;
letUserSelectRow = NO;
self.tableview.scrollEnabled = NO;

}

- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText
{

[copyListofItems removeAllObjects];

if([searchText length] > 0)
{
[ovController.view removeFromSuperview];
searching = YES;
letUserSelectRow = YES;
self.tableview.scrollEnabled = YES;
[self searchTableView];
}
else
{
[self.tableview insertSubview:ovController.view aboveSubview:self.parentViewController.view];
searching = NO;
letUserSelectRow = NO;
self.tableview.scrollEnabled = NO;
}

}
- (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar
{
}
- (void) searchBarCancelButtonClicked:(UISearchBar *)theSearchBar
{
[self doneSearching_Clicked:theSearchBar];
}
- (void) searchTableView
{
NSString *searchText = self.searchbar.text;

NSMutableArray *searchArray = [[NSMutableArray alloc] init];
NSEnumerator *userIterator= [usernames objectEnumerator];
NSString *username;

while(username = [userIterator nextObject])
{
[searchArray addObject:username];
}

//NSPredicate *searchpredicate = [NSPredicate predicateWithFormat:@"SELF contains %@",searchText];

//[searchArray filterUsingPredicate:searchpredicate];

for (NSString *sTemp in searchArray)
{
if([[sTemp componentsSeparatedByString:@" "] count ]>1)
{
NSArray *split = [[NSArray alloc] initWithArray:[sTemp componentsSeparatedByString:@" "]];
if ([split count]>0)
{
NSRange titleResultsRange = [[split objectAtIndex:0] rangeOfString:searchText options:(NSCaseInsensitiveSearch|NSAnchoredSearch)];

NSRange titleResultsRange2 = [[split objectAtIndex:1] rangeOfString:searchText options:(NSCaseInsensitiveSearch|NSAnchoredSearch)];
if ((titleResultsRange.length > 0) || (titleResultsRange2.length > 0))
{
[copyListofItems addObject:sTemp];
}
}
}
else
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:(NSCaseInsensitiveSearch|NSAnchoredSearch)];
if (titleResultsRange.length > 0)
{
[copyListofItems addObject:sTemp];
}
}

}
[searchArray release];

}

- (void) doneSearching_Clicked:(id)sender
{
self.navigationController.navigationBarHidden = NO;
searchbar.showsCancelButton = NO;
searchbar.text = @"";
[searchbar resignFirstResponder];

letUserSelectRow = YES;
searching = NO;
self.navigationItem.rightBarButtonItem = nil;
self.tableview.scrollEnabled = YES;

[ovController.view removeFromSuperview];
[ovController release];
ovController = nil;
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:@"Refresh" style:UIBarButtonSystemItemDone target:self action:@selector(loadData)] autorelease];

[self.tableview reloadData];
}

customize cell

make a class

// CustomCell.h
// iwebservice
//

#import


@interface CustomCell : UITableViewCell {
UILabel *primaryLabel;

UILabel *secondaryLabel;

UIImageView *myImageView;
}
@property(nonatomic,retain)UILabel *primaryLabel;

@property(nonatomic,retain)UILabel *secondaryLabel;

@property(nonatomic,retain)UIImageView *myImageView;
@end

now put the code in its m file

// CustomCell.m
// iwebservice


#import "CustomCell.h"


@implementation CustomCell
@synthesize primaryLabel,secondaryLabel,myImageView;
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {

if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {

// Initialization code

primaryLabel = [[UILabel alloc]init];

primaryLabel.textAlignment = UITextAlignmentLeft;

primaryLabel.font = [UIFont systemFontOfSize:14];

secondaryLabel = [[UILabel alloc]init];

secondaryLabel.textAlignment = UITextAlignmentLeft;

secondaryLabel.font = [UIFont systemFontOfSize:8];

myImageView = [[UIImageView alloc]init];

[self.contentView addSubview:primaryLabel];

[self.contentView addSubview:secondaryLabel];

[self.contentView addSubview:myImageView];

}

return self;

}

- (void)layoutSubviews {

[super layoutSubviews];

CGRect contentRect = self.contentView.bounds;

CGFloat boundsX = contentRect.origin.x;

CGRect frame;

frame= CGRectMake(boundsX+10 ,0, 50, 50);

myImageView.frame = frame;

frame= CGRectMake(boundsX+70 ,5, 200, 25);

primaryLabel.frame = frame;

frame= CGRectMake(boundsX+70 ,30, 100, 15);

secondaryLabel.frame = frame;

}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

[super setSelected:selected animated:animated];

// Configure the view for the selected state
}


- (void)dealloc {
[super dealloc];
}


@end

now you can easily use it in your code
example,

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"CellIdentifier";

CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[CustomCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}

if(searching)
{
cell.primaryLabel.text = [copyListofItems objectAtIndex:indexPath.row];
}
else
{
if(indexPath.section ==0)
{
return nil;
}

NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section-1];
NSArray *array = [dictionary objectForKey:@"Country"];
NSString *cellValue = [array objectAtIndex:indexPath.row];

cell.primaryLabel.text = cellValue;

}

cell.primaryLabel.backgroundColor = [UIColor clearColor];
cell.primaryLabel.textColor = [UIColor colorWithRed:139.0/256 green:196.0/256 blue:40.0/256 alpha:100];
cell.primaryLabel.highlightedTextColor = [UIColor blackColor];

cell.secondaryLabel.text =[finalsgn objectForKey:[final objectForKey:cell.primaryLabel.text] ];
cell.secondaryLabel.backgroundColor = [UIColor clearColor];
cell.secondaryLabel.textColor = [UIColor colorWithRed:144.0/256 green:154.0/256 blue:47.0/256 alpha:100];
cell.secondaryLabel.highlightedTextColor = [UIColor blackColor];

UIImageView *cellBG = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"add-cell.jpg"]];
[cell setBackgroundView:cellBG];
[cellBG release];

UIImageView *cellbkBG = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"add-flate.jpg"]];
cell.selectedBackgroundView =cellbkBG;
cell.selectedBackgroundView.clearsContextBeforeDrawing = NO;
[cellbkBG release];

[cell.backgroundView setNeedsDisplay];

return cell;

}

enjoy !

make sections in uitableview

use below code and do it

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if([listOfItems count]==0)
{
return 0;
}
if (searching)
{
return 1;
}
else
{

UILocalizedIndexedCollation *currentCollation = [UILocalizedIndexedCollation currentCollation];
return [currentCollation.sectionTitles count];
}
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (searching)
{
return [copyListofItems count];
}
else
{
if (section==0) {
return 0;
}
if(section<27)
{
NSDictionary *dictionary = [listOfItems objectAtIndex:section-1];
NSArray *array = [dictionary objectForKey:@"Country"];

return [array count];

}
else {
return 0;
}

}
}

now yu need to give titles them

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
if(searching)
return nil;
return [[NSArray arrayWithObject:UITableViewIndexSearch] arrayByAddingObjectsFromArray:
[[UILocalizedIndexedCollation currentCollation] sectionIndexTitles]];
}


- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
if(searching)
{
return -1;
}
else
{
UILocalizedIndexedCollation *currentCollation = [UILocalizedIndexedCollation currentCollation];

if (index>0)
{
return [currentCollation sectionForSectionIndexTitleAtIndex:index];
}
else
{
return 0;
}

}
}
enjoy!

perform selector on main thread

some times there is a need to call some methods on main thread like reloading uitableview

here it is how to do it

[self.tableview performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];

enjoy!

how to load uitableview in background

make a method like below

- (void) loadData {
self.navigationItem.rightBarButtonItem = nil;
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];

[activityIndicator startAnimating];

UIBarButtonItem *activityItem = [[UIBarButtonItem alloc] initWithCustomView:activityIndicator];

[activityIndicator release];

self.navigationItem.rightBarButtonItem = activityItem;

[activityItem release];



NSOperationQueue *queue = [NSOperationQueue new];

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(Loadtabledata)
object:nil];

[queue addOperation:operation];
[operation release];
}

and now make main method

-(void) Loadtabledata
{
searching = NO;
letUserSelectRow = YES;
//listOfItems2 = [listOfItems mutableCopy];
[listOfItems2 removeAllObjects];
DataController *controller = [[DataController alloc] init];
self.dataController = controller;
[self.dataController SetFilter:searchfilter];
[controller release];

searchbar.autocorrectionType = UITextAutocorrectionTypeNo;
usernames = [self.dataController GetList];
NSMutableArray *IDs = [NSMutableArray array];
IDs = [self.dataController GetIds];

NSEnumerator *userIterator= [usernames objectEnumerator];
NSString *username;
NSMutableArray *array = [NSMutableArray array];
while(username = [userIterator nextObject])
{
[array addObject:username];
}
NSEnumerator *idIterator= [IDs objectEnumerator];
NSMutableArray *arrayid = [NSMutableArray array];
while(IDs = [idIterator nextObject])
{
[arrayid addObject:IDs];
}

final = [[NSMutableDictionary alloc] initWithObjects:arrayid forKeys:array];

[array sortUsingSelector:@selector(compare:)];


NSArray *charArray = [[NSArray alloc] initWithObjects: @"a", @"b", @"c", @"d",
@"e", @"f", @"g", @"h", @"i", @"j", @"k", @"l", @"m", @"n",
@"o", @"p", @"q", @"r", @"s", @"t", @"u", @"v", @"w",
@"x", @"y", @"z", nil];

for (int a = 0; a < 26; a++)
{
NSMutableArray *array2 = [NSMutableArray arrayWithArray:usernames];
NSString *tmpValue = nil;
tmpValue =[charArray objectAtIndex: a];
NSPredicate *gpredicate = [NSPredicate predicateWithFormat:@"SELF beginswith %@ || SELF beginswith %@ ",tmpValue,[tmpValue uppercaseString]];
[array2 filterUsingPredicate:gpredicate];
NSDictionary *tempdict = [NSDictionary dictionaryWithObject:array2 forKey:@"Country"];
[listOfItems2 addObject:tempdict];
}
NSMutableArray *array2 = [NSMutableArray arrayWithArray:array];
NSPredicate *gpredicate = [NSPredicate predicateWithFormat:@"!SELF MATCHES %@",@"([a-zA-Z]).*"];
[array2 filterUsingPredicate:gpredicate];
NSDictionary *tempdict = [NSDictionary dictionaryWithObject:array2 forKey:@"Country"];
[listOfItems2 addObject:tempdict];

NSMutableArray *subgroupnames = [[NSMutableArray alloc]init];
subgroupnames = [self.dataController Getsgns];

NSEnumerator *sgnIterator= [subgroupnames objectEnumerator];
NSMutableArray *arraysgn = [NSMutableArray array];
while(subgroupnames = [sgnIterator nextObject])
{
[arraysgn addObject:subgroupnames];
}
finalsgn = [[NSMutableDictionary alloc] initWithObjects:arraysgn forKeys:arrayid];

NSMutableArray *mobs = [[NSMutableArray alloc]init];
mobs = [self.dataController Getmobiles];

NSEnumerator *mobIterator= [mobs objectEnumerator];
NSMutableArray *arraymob = [NSMutableArray array];
while(mobs = [mobIterator nextObject])
{
[arraymob addObject:mobs];
}

mobilnos = [[NSMutableDictionary alloc] initWithObjects:arraymob forKeys:arrayid];

NSMutableArray *ems = [[NSMutableArray alloc]init];
ems = [self.dataController GetEmails];

NSEnumerator *emsIterator= [ems objectEnumerator];
NSMutableArray *arrayem = [NSMutableArray array];
while(ems = [emsIterator nextObject])
{
[arrayem addObject:ems];
}

emails = [[NSMutableDictionary alloc] initWithObjects:arrayem forKeys:arrayid];

NSMutableArray *fes = [[NSMutableArray alloc]init];
fes = [self.dataController GetFexs];

NSEnumerator *fesIterator= [fes objectEnumerator];
NSMutableArray *arrayfe = [NSMutableArray array];
while(fes = [fesIterator nextObject])
{
[arrayfe addObject:fes];
}

fexs = [[NSMutableDictionary alloc] initWithObjects:arrayfe forKeys:arrayid];

NSMutableArray *bds = [[NSMutableArray alloc]init];
bds = [self.dataController GetBirthdays];

NSEnumerator *bdsIterator= [bds objectEnumerator];
NSMutableArray *arraybd = [NSMutableArray array];
while(bds = [bdsIterator nextObject])
{
[arraybd addObject:bds];
}

birthdays = [[NSMutableDictionary alloc] initWithObjects:arraybd forKeys:arrayid];

NSMutableArray *ans = [[NSMutableArray alloc]init];
ans = [self.dataController GetAnniversarydays];

NSEnumerator *ansIterator= [ans objectEnumerator];
NSMutableArray *arrayan = [NSMutableArray array];
while(ans = [ansIterator nextObject])
{
[arrayan addObject:ans];
}

annidays = [[NSMutableDictionary alloc] initWithObjects:arrayan forKeys:arrayid];

if([listOfItems isEqualToArray:listOfItems2 ])
{
}
else {
listOfItems = [listOfItems2 copy];
finaltmp = [final copy];
[self.tableview performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];


}

[self writeToPlist];

self.navigationItem.rightBarButtonItem = nil;
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:@"Refresh" style:UIBarButtonSystemItemDone target:self action:@selector(loadData)] autorelease];

}

NET Web Service Classes

Make a class WebServiceHelper.h and put the code below

// WebServiceHelper.h
//

#import


@interface WebServiceHelper : NSObject {
NSString *XMLNameSpace;
NSString *XMLURLAddress;
NSString *MethodName;
NSString *SOAPActionURL;
NSMutableDictionary *MethodParameters;
NSMutableString *MethodParametersAsString;
}
@property(nonatomic, retain) NSString *XMLNameSpace;
@property(nonatomic, retain) NSString *XMLURLAddress;
@property(nonatomic, retain) NSString *MethodName;
@property(nonatomic, retain) NSMutableDictionary *MethodParameters;
@property(nonatomic, retain) NSString *SOAPActionURL;
@property(nonatomic, retain) NSMutableString *MethodParametersAsString;

- (NSMutableData*)initiateConnection;
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
@end

Now in its .m file put the code below

// WebServiceHelper.m
//

#import "WebServiceHelper.h"
#import "XmlDataSetParser.h"

@implementation WebServiceHelper
@synthesize MethodName;
@synthesize MethodParameters;
@synthesize XMLNameSpace;
@synthesize XMLURLAddress;
@synthesize SOAPActionURL;
@synthesize MethodParametersAsString;
- (NSMutableData*)initiateConnection
{


NSMutableString *sRequest = [[NSMutableString alloc] init];
self.SOAPActionURL = [NSString stringWithFormat:@"%@%@",self.XMLNameSpace, self.MethodName];
[sRequest appendString:@""];
[sRequest appendString:@""];
[sRequest appendString:@""];
[sRequest appendString:[NSString stringWithFormat:@"<%@ xmlns=\"%@\">",MethodName, XMLNameSpace]];
if(MethodParametersAsString != nil) [sRequest appendString:MethodParametersAsString];

NSEnumerator *tableIterator = [MethodParameters keyEnumerator];
NSString *keyID;
while(keyID = [tableIterator nextObject])
{
[sRequest appendString:[NSString stringWithFormat:@"<%@>%@", keyID, [MethodParameters objectForKey:keyID], keyID]];
}

[sRequest appendString:[NSString stringWithFormat:@"", MethodName]];
[sRequest appendString:@"
"];
[sRequest appendString:@"
"];

NSURL *myWebserverURL = [NSURL URLWithString:XMLURLAddress];

//NSLog(@"%@",sRequest);

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myWebserverURL];
[request addValue:[NSString stringWithFormat:@"%d",sRequest.length] forHTTPHeaderField:@"Content-length"];
[request addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"beta.ecoscrm.com" forHTTPHeaderField:@"Host"];
[request addValue:SOAPActionURL forHTTPHeaderField:@"SOAPAction"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[sRequest dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
NSMutableData *myMutableData;

if(conn)
{
myMutableData=[[NSMutableData data] retain];
}
else {
NSLog(@"CONNECTION FAILED");

}
[NSURLConnection connectionWithRequest:request delegate:self];

NSError *WSerror;
NSURLResponse *WSresponse;

myMutableData = [[NSMutableData alloc] initWithData:[NSURLConnection sendSynchronousRequest:request returningResponse:&WSresponse error:&WSerror]];

NSString *theXml = [[NSString alloc]initWithBytes:[myMutableData mutableBytes] length:[myMutableData length] encoding:NSUTF8StringEncoding];

NSLog(@"%@",theXml);
[sRequest release];

return myMutableData;
[myMutableData release];
}
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host
{
return YES;
}
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host
{

}
@end

The class is used to call net web service which will return xml schema

you need to make two more classes now

make a class DataSet.h

// DataSet.h


#import


@interface DataSet : NSObject {
NSString *DataSetName;
NSMutableDictionary *Tables;

}
@property (nonatomic, retain) NSMutableDictionary *Tables;
@property (nonatomic, retain) NSString *DataSetName;
-(id)initWithXMLData:(NSMutableData *)data;
-(NSString *)getFirstForTableAndColumn:(NSString *)tableName col:(NSString *)colName;
-(NSMutableDictionary *)getRowsForTableAndColumn:(NSString *)tableName col:(NSString *)colName;
-(NSMutableDictionary *)getRowsForTableAndColumnWhereEqualsString:(NSString *)tableName col:(NSString *)colName where:(NSString *)wherevalue;
-(NSMutableDictionary *)getRowsForTableAndColumnWhereColumnEqualsString:(NSString *)tableName col:(NSString *)colName whereColumn:(NSString *)wherecolumn whereValue:(NSString *)wherevalue;
-(NSMutableDictionary *)getRowsForTableAndColumnWhereEqualsStrings:(NSString *)tableName col:(NSString *)colName where:(NSArray *)wherevalues;
-(void) dealloc;
@end

now put the code below in its .m file

// DataSet.m
//

#import "DataSet.h"
#import "XMLDataSetParser.h"

@implementation DataSet
@synthesize Tables;
@synthesize DataSetName;

-(id)initWithXMLData:(NSMutableData *)data
{

NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];

XmlDataSetParser *xmParser = [[XmlDataSetParser alloc] init];

[parser setDelegate:xmParser];

[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];

[parser parse];


NSString *theXml = [[NSString alloc]initWithBytes:[data mutableBytes] length:[data length] encoding:NSUTF8StringEncoding];
// NSLog([[NSString alloc] initWithFormat:@"response:%@", theXml, nil]);

self.Tables = [[xmParser thisDataset] Tables];
[parser release];
[xmParser release];

return self;
}

-(NSMutableDictionary *)getRowsForTableAndColumn:(NSString *)tableName col:(NSString *)colName
{
NSMutableDictionary *returnDictionary = [[NSMutableDictionary alloc] init];
NSEnumerator *tableIterator = [self.Tables keyEnumerator];
NSString *tableKey;


while(tableKey = [tableIterator nextObject])
{

if([tableKey isEqualToString:tableName])
{

NSMutableArray *sortedKeys = [NSMutableArray arrayWithArray: [[self.Tables objectForKey:tableKey] allKeys]];
[sortedKeys sortUsingSelector:@selector(compare:)];


NSEnumerator *rowIterator = [sortedKeys objectEnumerator];
NSString *rowKey;


while(rowKey = [rowIterator nextObject])
{

if([rowKey rangeOfString:colName].location != NSNotFound)
{
NSArray *split = [rowKey componentsSeparatedByString:@"--"];

if([[split objectAtIndex:0] isEqualToString:colName])
{
[returnDictionary setObject:[[self.Tables objectForKey:tableKey] objectForKey:rowKey] forKey:[split objectAtIndex:1]];

}
}
}
}

}
if ([returnDictionary count] > 0)
{

return returnDictionary;
}
else
{
return nil;
}

[returnDictionary release];
}

-(NSString *)getFirstForTableAndColumn:(NSString *)tableName col:(NSString *)colName
{
NSMutableDictionary *returnDictionary = [[NSMutableDictionary alloc] init];
NSEnumerator *tableIterator = [self.Tables keyEnumerator];
NSString *tableKey;


while(tableKey = [tableIterator nextObject])
{

if([tableKey isEqualToString:tableName])
{

NSMutableArray *sortedKeys = [NSMutableArray arrayWithArray: [[self.Tables objectForKey:tableKey] allKeys]];
[sortedKeys sortUsingSelector:@selector(compare:)];


NSEnumerator *rowIterator = [sortedKeys objectEnumerator];
NSString *rowKey;


while(rowKey = [rowIterator nextObject])
{

if([rowKey rangeOfString:colName].location != NSNotFound)
{
NSArray *split = [rowKey componentsSeparatedByString:@"--"];

if([[split objectAtIndex:0] isEqualToString:colName])
{
[returnDictionary setObject:[[self.Tables objectForKey:tableKey] objectForKey:rowKey] forKey:[split objectAtIndex:1]];

}
}
}
}

}
if ([returnDictionary count] > 0)
{
return [returnDictionary objectForKey:@"1"];
}
else
{
return nil;
}

[returnDictionary release];
}

-(NSMutableDictionary *)getRowsForTableAndColumnWhereEqualsStrings:(NSString *)tableName col:(NSString *)colName where:(NSArray *)wherevalues
{

return nil;
}

-(NSMutableDictionary *)getRowsForTableAndColumnWhereEqualsString:(NSString *)tableName col:(NSString *)colName where:(NSString *)wherevalue
{
NSMutableDictionary *returnDictionary = [[NSMutableDictionary alloc] init];
NSEnumerator *tableIterator = [self.Tables keyEnumerator];
NSString *tableKey;


while(tableKey = [tableIterator nextObject])
{

if([tableKey isEqualToString:tableName])
{

NSMutableArray *sortedKeys = [NSMutableArray arrayWithArray: [[self.Tables objectForKey:tableKey] allKeys]];
[sortedKeys sortUsingSelector:@selector(compare:)];


NSEnumerator *rowIterator = [sortedKeys objectEnumerator];
NSString *rowKey;

while(rowKey = [rowIterator nextObject])
{

if([rowKey rangeOfString:colName].location != NSNotFound)
{

NSArray *split = [rowKey componentsSeparatedByString:@"--"];
NSString *rowData = [[self.Tables objectForKey:tableKey] objectForKey:rowKey];
if ([rowData isEqualToString:wherevalue])
{
[returnDictionary setObject:rowData forKey:[split objectAtIndex:1]];
}

}
}
}
}

if ([returnDictionary count] > 0)
{

return returnDictionary;
}
else
{
return nil;
}

[returnDictionary release];
}
-(NSMutableDictionary *)getRowsForTableAndColumnWhereColumnEqualsString:(NSString *)tableName col:(NSString *)colName whereColumn:(NSString *)wherecolumn whereValue:(NSString *)wherevalue
{
NSMutableDictionary *returnDictionary = [[NSMutableDictionary alloc] init];
NSEnumerator *tableIterator = [self.Tables keyEnumerator];
NSString *tableKey;


while(tableKey = [tableIterator nextObject])
{


if([tableKey isEqualToString:tableName])
{

NSMutableArray *sortedKeys = [NSMutableArray arrayWithArray: [[self.Tables objectForKey:tableKey] allKeys]];

[sortedKeys sortUsingSelector:@selector(compare:)];

NSEnumerator *rowIteratorWhereColumn = [sortedKeys objectEnumerator];
NSString *rowWhereKey;
while(rowWhereKey = [rowIteratorWhereColumn nextObject])
{

if([rowWhereKey rangeOfString:wherecolumn].location != NSNotFound)
{

NSArray *split = [rowWhereKey componentsSeparatedByString:@"--"];

NSString *coldata = [[self.Tables objectForKey:tableKey] objectForKey:rowWhereKey];

if([coldata isEqualToString:wherevalue])
{
if( [[self.Tables objectForKey:tableKey] objectForKey:[NSString stringWithFormat:@"%@--%@", colName, [split objectAtIndex:1]]]==nil)
{
}
else
{
[returnDictionary setObject:[[self.Tables objectForKey:tableKey] objectForKey:[NSString stringWithFormat:@"%@--%@", colName, [split objectAtIndex:1]]] forKey:[split objectAtIndex:1]];
}
}
}
}
}
}

if ([returnDictionary count] > 0)
{

return returnDictionary;
}
else
{
return nil;
}

[returnDictionary release];
}

-(void)dealloc
{
self.Tables = nil;
[super dealloc];

}

@end

this will create dataset

u need one more class to parse ur xml

make class

// XMLDataSetParser.h
//


#import
#import "DataSet.h"

@interface XmlDataSetParser : NSObject {
DataSet *thisDataset;
Boolean beginDataset;
Boolean beginTable;
NSString *currentTable;
NSString *currentColumn;
}

@property (nonatomic, retain) DataSet *thisDataset;
@property (nonatomic, retain) NSString *currentTable;
@property (nonatomic, retain) NSString *currentColumn;



- (void)parserDidStartDocument:(NSXMLParser *)parser;
- (void)parserDidEndDocument:(NSXMLParser *)parser;
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict;
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;

@end

put the code below in its m file

// XMLDataSetParser.m
//


#import "XmlDataSetParser.h"
#import "DataSet.h"

@implementation XmlDataSetParser
@synthesize thisDataset;
@synthesize currentTable;
@synthesize currentColumn;

#pragma XML Parser Delegate Methods
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
thisDataset = [[DataSet alloc] init];
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
}


- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if (beginDataset == YES)
{

thisDataset.DataSetName = elementName;
thisDataset.Tables =[[NSMutableDictionary alloc] init];
beginDataset = NO;
}
else
{
if ([elementName isEqualToString:@"diffgr:diffgram"]) {

beginDataset = YES;
}

if (thisDataset.DataSetName != nil && beginTable == YES)
{

if([currentColumn isEqualToString:@""] || currentColumn == nil)
{
currentColumn = elementName;
}
}
if (thisDataset.DataSetName != nil && beginTable == NO)
{

if([thisDataset.Tables objectForKey:elementName] == nil)
{
[thisDataset.Tables setObject: [[NSMutableDictionary alloc] init] forKey:elementName];
currentTable = elementName;

}
beginTable = YES;
}

}


}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if(beginTable == YES && [elementName isEqualToString:currentTable])
{
beginTable = NO;
}

if(beginTable == YES && currentColumn != @"")
{
currentColumn = @"";
}

}


- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSString * errorString = [NSString stringWithFormat:@"Unable to convert XML into dataset: %@", [parseError description]];
NSLog(@"error parsing XML: %@", errorString);

UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Error loading content" message:errorString delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{

NSMutableDictionary *table = [[NSMutableDictionary alloc] initWithDictionary:[thisDataset.Tables objectForKey:currentTable]];

NSEnumerator *myIterator = [table keyEnumerator];
NSString *aKey;
NSInteger intCnt = 0;

while(aKey = [myIterator nextObject])
{

NSArray *split = [[NSArray alloc] initWithArray:[aKey componentsSeparatedByString:@"--"]];

if([[split objectAtIndex:0] isEqualToString:currentColumn])
{
intCnt++;
}
[split release];
}

NSString *colName = [[NSString alloc] initWithFormat:@"%@--%d", self.currentColumn, (intCnt+1), nil];
[table setObject:string forKey:colName];
[thisDataset.Tables setObject:table forKey:currentTable];
[colName release];
[table release];
}

@end

now u have all the classes defined for web service

now here below i show you how to use it

#import "DataSet.h"
#import "WebServiceHelper.h"

import the above in class in which u wanna call web service
now use below code

WebServiceHelper *DataCon = [[WebServiceHelper alloc] init];


DataCon.XMLNameSpace = @"http://tempuri.org/";
DataCon.XMLURLAddress = @"http://yourdomain.com/webservicesfolder/service1.asmx";
DataCon.MethodName = @"MyMethodName";
DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
[DataCon.MethodParameters setObject:[[NSUserDefaults standardUserDefaults] stringForKey:@"name_preference"] forKey:@"UserName"];
[DataCon.MethodParameters setObject:[[NSUserDefaults standardUserDefaults] stringForKey:@"password_preference"] forKey:@"Password"];
[DataCon.MethodParameters setObject:search forKey:@"GroupId"];
tdata = [DataCon initiateConnection];

DataSet *dsMyDataSet = [[DataSet alloc] initWithXMLData:tdata];

NSMutableArray *Name = [[NSMutableDictionary alloc] init];
NSMutableArray *ID = [[NSMutableDictionary alloc] init];
NSMutableArray *SGN = [[NSMutableDictionary alloc]init];

ID = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"Id"];
Name = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"DisplayName"];
SGN = [dsMyDataSet getRowsForTableAndColumn:@"_x0030_" col:@"SubGroupName"];

Enjoyy !

Soap Envelope in Xcode

ommunicating with the outside world is one of the ways to make your iPhone applications interesting and useful. This is especially true today where they are so many web services that provide so much useful functionality. However, consuming web services in iPhone is not for the faint-of-heart. Unlike other development tools (such as Microsoft Visual Studio), Xcode does not have built-in tools that make consuming web services easy. Everything must be done by hand and you need to know how to form the relevant XML messages to send to the web services and then parse the returning XML result.


This article will give you a good understanding of how to communicate with XML web services from within your iPhone application, and the examples will provide a solid foundation for consuming other web services in your own projects.


Consuming Web Services


 
Figure 1. IPToCountry Web Service: This web service exposes two web methods.

Before beginning an Xcode project to consume a web service, examining a real web service to see the different ways you can consume is worthwhile. My favorite example is to use an ASMX XML web service created using .NET. For discussion purposes, here's a look at a web service called IPToCountry, which lets you supply an IP address and returns the country to which the IP address belongs.


The IPToCountry web service is located at http://www.ecubicle.net/iptocountry.asmx. If you use Safari to load this URL, you'll see that it exposes two web methods as shown in Figure 1.



As an example, the FindCountryAsXML returns the result (the country) as an XML string. Clicking the FindCountryAsXML link reveals the page shown in Figure 2.


 
Figure 2. FindCountryAsXml Service: Testing the web service through a browser interface shows the XML packets exchanged between the client and the server.

The important parts are the sections following the Test section of the page. They detail the various ways in which you can consume the web service. In the .NET world, accessing the web service is a pretty straightforward affair—Visual Studio provides a built-in tool that automatically creates a web proxy service object for the web service when you download the WSDL document. For iPhone development, you need to get your hands dirty, so it's far more important to understand the underlying mechanics of consuming web services.


Using SOAP 1.1


One way to consume this web service is to use SOAP (Simple Object Access Protocol). When using SOAP, you use the HTTP POST method to send a request to the web service, as shown in the following example:



POST /iptocountry.asmx HTTP/1.1
Host: www.ecubicle.net
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.ecubicle.net/webservices/FindCountryAsXml"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<FindCountryAsXml xmlns="http://www.ecubicle.net/webservices/">
<V4IPAddress>string</V4IPAddress>

</FindCountryAsXml>
</soap:Body>
</soap:Envelope>


The parts of the code in bold are the placeholders where you need to substitute the actual values. A couple of important things to note from the above:


  • The URL for the web service is http://www.ecubicle.net/iptocountry.asmx.

  • The URL for the SOAPAction attribute is http://www.ecubicle.net/webservices/FindCountryAsXml.


  • The Content-Type for the request is text/xml; charset=utf-8.

  • The HTTP method is POST.

  • The SOAP request is shown below:

    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

    <soap:Body>
    <FindCountryAsXml xmlns="http://www.ecubicle.net/webservices/">
    <V4IPAddress>string</V4IPAddress>
    </FindCountryAsXml>
    </soap:Body>

    </soap:Envelope>


  • The Content-Length of the SOAP request is the total number of characters in the complete SOAP request.



The web service will return a response formatted as follows:


HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<FindCountryAsXmlResponse
xmlns="http://www.ecubicle.net/webservices/">
<FindCountryAsXmlResult>xml result</FindCountryAsXmlResult>
</FindCountryAsXmlResponse>

</soap:Body>
</soap:Envelope>


For a real request, the result (the country) will be enclosed within the block of XML code (the bold placeholder in the preceding example). You would need to extract it from the XML result.

Friday, June 4, 2010

Intercepting status bar touches on the iPhone

You can configure your iPhone applications so that a touch in the status bar will scroll a UIScrollView to the top. I'll show you how you can intercept this touch event to use status bar touches for other purposes. The sample application will show a hidden drawer that slides out from the status bar when you tap it.
Touches in the status bar

A lesser known user-interface feature on the iPhone is that touches in the status bar will usually scroll the main UIScrollView to the top, providing a quick way to scroll to the top of long documents.

This will work in your application when exactly one UIScrollView returns YES for the scrollsToTop property (YES is the default). If more than one UIScrollView returns YES for this property (or the UIScrollView's delegate returns NO from scrollViewWillScrollToTop:) the scroll to top functionality will be disabled.

That's the ordinary functionality but how do we achieve different functionality?
The HiddenDrawer sample appliction



These screenshots show the HiddenDrawer sample application. When the status bar is tapped on the left, the hidden drawer animates out from under the status bar, resulting in the state shown on the right.
Stealing status bar touch events

The trickiest part of the sample application is detecting a touch in the status bar.

By implementing a custom setContentOffset:animated: method on a UITableView and setting a breakpoint in that method, you can see in the debugger stack that the UIApplication sendEvent: method is invoked for status bar touches, so that's where we'll begin.
CustomApplication

Overriding UIApplication is extremely rare so I'll explain how to make it work. Once you create the subclass of UIApplication you need to tell the program to use that subclass. In Cocoa Senior (Mac OS X) you specify application subclasses in the Info.plist file. In Cocoa Touch, you specify custom application subclasses by name in the UIApplicationMain function in the main.m file:

int retVal = UIApplicationMain(argc, argv, @"CustomApplication", nil);

sendEvent:

The only method override we need in CustomApplication is sendEvent:. The difficult part is then working out from the UIEvent which events are status bar touch events — unfortunately, the allTouches method returns an empty array for status bar touches.

Instead, we delve into the secret GSEvent.

I previously accessed GSEvent in my post Synthesizing a touch event on the iPhone. In that post, I created a PublicEvent class and a fake GSEventProxy class to access the required fields. This time, I'm going to use a different approach and jump straight to the data I need.

- (void)sendEvent:(UIEvent *)anEvent
{
#define GS_EVENT_TYPE_OFFSET 2
#define GS_EVENT_X_OFFSET 6
#define GS_EVENT_Y_OFFSET 7
#define STATUS_BAR_TOUCH_DOWN 1015

// Traverse from the UIEvent to the GSEvent to the type
int *eventMemory = (int *)[anEvent performSelector:@selector(_gsEvent)];
int eventType = eventMemory[GS_EVENT_TYPE_OFFSET];

// Look for status bar touches by event type
if (eventType == STATUS_BAR_TOUCH_DOWN)
{
// The next 6 lines aren't essential but if you want to know where the
// touch coordinates live, here they are:
int xMemory = eventMemory[GS_EVENT_X_OFFSET];
int yMemory = eventMemory[GS_EVENT_Y_OFFSET];

typedef union {int intValue; float floatValue;} Int2Float;
float x = ((Int2Float)xMemory).floatValue;
float y = ((Int2Float)yMemory).floatValue;

NSLog(@"Status bar down at %f, %f", x, y);

// Send a message to the delegate to handle the action
[(HiddenDrawerAppDelegate *)self.delegate toggleDrawer];
}
else
{
[super sendEvent:anEvent];
}
}

You may be curious to know where the OFFSET values come from. The answer is that I spent a while staring at the raw memory values in the GSEvent object while deliberately causing status bar and other touch events — nothing fancier than that. It's tricky and unreliable. If it works at all in iPhoneSDK3.0, it'll be pure luck.

I also use a union here. This is because I step through memory as ints and in C, a basic cast from int to float causes a value conversion (I want a reinterpret, not a value conversion).

I also chose to suppress status bar touch events going through to the UITableView by the normal route. If you want to re-enable this behavior, you can take the [super sendEvent:anEvent]; line out of the else block and put it in the main method body.
Animating the drawer

The sendEvent: implementation above invokes the toggleDrawer method on the application's delegate.

All that's required is to animate the drawer's view in and push the table's view down:

drawerController = [[HiddenDrawerViewController alloc] init];

// Position the drawer below the status bar
CGRect drawerFrame = drawerController.view.frame;
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
drawerFrame.origin.x = statusBarFrame.origin.x;
drawerFrame.size.width = statusBarFrame.size.width;
drawerFrame.origin.y = statusBarFrame.origin.y + statusBarFrame.size.height;

// For the animation, move the drawer up by its own height.
drawerFrame.origin.y -= drawerFrame.size.height;

// Place the drawer and add it to the window
drawerController.view.frame = drawerFrame;
[window addSubview:drawerController.view];

// Start the animation
[UIView beginAnimations:nil context:nil];

// Move the table down
CGRect tableFrame = viewController.view.frame;
tableFrame.origin.y += drawerFrame.size.height;
viewController.view.frame = tableFrame;

// Move the drawer down
drawerFrame.origin.y += drawerFrame.size.height;
drawerController.view.frame = drawerFrame;

// Commit the animation
[UIView commitAnimations];

If you download the whole project, you'll see that there's also an animate up and remove branch that gets run if the drawerController already exists.
Conclusion

You can download the HiddenDrawer sample project (30kB) to see the whole application in action.

A hidden drawer under the status bar isn't necessarily something that every iPhone application should have but the obscure, secretive nature of it appeals to me.

The approach of determining which UIEvent we want by the type field in the GSEvent is a little precarious. Apple are free to change the structure of GSEvent at any time, which could cause your application to misbehave or crash so this type of code would need to be tested on each iPhone OS release to ensure that it still works.

Display YouTube Videos Without Exiting Your Application

if you’d like to play a YouTube video inside your application there are two common ways to do this, by launching the YouTube player and by using a UIWebview.
Launch Native YouTube Application

This approach will exit your application and begin the YouTube player on the iPhone:

[[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://www.youtube.com/watch?v=gczw0WRmHQU"]];

Clickable Thumbnail and UIWebview

If you’ve noticed in Safari on the iPhone, when the browser finds a YouTube video reference, a clickable link is created, which will start the movie when tapped without leaving Safari.

We can use the same approach within an iPhone application using a UIWebView, including a clickable link with a poster frame from the movie.

For this example I have created a separate class that subclasses UIWebView:

@interface YouTubeView : UIWebView
{
}

- (YouTubeView *)initWithStringAsURL:(NSString *)urlString frame:(CGRect)frame;

@end

Here’s the implementation of the class:

#import "YouTubeView.h"

@implementation YouTubeView

#pragma mark -
#pragma mark Initialization

- (YouTubeView *)initWithStringAsURL:(NSString *)urlString frame:(CGRect)frame;
{
if (self = [super init])
{
// Create webview with requested frame size
self = [[UIWebView alloc] initWithFrame:frame];

// HTML to embed YouTube video
NSString *youTubeVideoHTML = @"<html><head>\
<body style=\"margin:0\">\

<embed id=\"yt\" src=\"%@\" type=\"application/x-shockwave-flash\" \

width=\"%0.0f\" height=\"%0.0f\"></embed>\
</body></html>"
;

 


// Populate HTML with the URL and requested frame size
NSString *html = [NSString stringWithFormat:youTubeVideoHTML, urlString, frame.size.width, frame.size.height];

// Load the html into the webview
[self loadHTMLString:html baseURL:nil];
}
return self;
}

#pragma mark -
#pragma mark Cleanup

- (void)dealloc
{
[super dealloc];
}

@end

The magic here is the HTML for embedding the video content, and notice how the HTML is populated with the video URL and the desired frame size.

We can now insert this view inside a ViewController class as shown here:


// Create view that will act as link to youtube video,
// centering the view
YouTubeView *youTubeView = [[YouTubeView alloc]
initWithStringAsURL:@"http://www.youtube.com/watch?v=gczw0WRmHQU"
frame:CGRectMake(100, 170, 120, 120)];

[[self view] addSubview:youTubeView];

Here is how the clickable link looks, the image on the left is before the poster frame has downloaded, the right includes the poster frame:




Tapping the link will start the movie in a webview.

The Basics of Protocols and Delegates

Apple offers a good overview of working with protocols in their Objective-C Programming Reference. However, sometimes a simple working example can go a long ways…
Introduction

Protocols can be helpful in a number of scenarios, a common usage is to define methods that are to be implemented by other classes. A familiar example is when using a tableview, your class implements the cellForRowAtIndexPath method which asks for cell content to insert into a table – the cellForRowAtIndexPath method is defined within the UITableViewDataSource protocol.

Let’s walk through a very simple example of defining and adopting a protocol.
Protocol Definition

Here is an example of a protocol which includes one method, notice the instance variable delegate is of type id, as it will be unknown at compile time the type of class that will adopt this protocol.

#import

@protocol ProcessDataDelegate
@required
- (void) processSuccessful: (BOOL)success;
@end

@interface ClassWithProtocol : NSObject
{
id delegate;
}

@property (retain) id delegate;

-(void)startSomeProcess;

@end

Protocol Implementation

Inside the implementation section for the interface defined above we need to do two things at a minimum – first synthesize the delegate instance variable and second, call the method defined in the protocol as needed (more on that in a moment).

Let’s look at a bare bones implementation of the ClassWithProtocol.m:

#import "ClassWithProtocol.h"

@implementation ClassWithProtocol

@synthesize delegate;

- (void)processComplete
{
[[self delegate] processSuccessful:YES];
}

-(void)startSomeProcess
{
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self
selector:@selector(processComplete) userInfo:nil repeats:YES];
}

@end

Understand this is a rather contrived example – the intention is to show how/where one might use a protocol. For the sake of discussion assume you have a class that is processing (or downloading) some type of data. Further, assume this class is called from another class to begin the processing. Chances are, at some point the caller will want to be notified that the class processing the data is done, this is where the protocol comes in.

In the calling class, the method defined in the protocol, processSuccessful, will be implemented and will be called from the object doing the processing, once it is complete.

For this example, inside the class where the protocol is defined, I have one method, startSomeProcess, which simply starts a timer and calls processComplete after 5 seconds. Inside processComplete the calling object will be notified through its delegate that the process is done.
Adopting the Protocol

To keep the example short, I am using the applicaton delegate as the class that adopts the protocol. Here is how the app delegate looks:

#import
#import "ClassWithProtocol.h"

@class testAppObject;

@interface TestAppDelegate : NSObject
{
UIWindow *window;
ClassWithProtocol *protocolTest;
}

@property (nonatomic, retain) UIWindow *window;

@end

A few things to note – ProcessDataDelegate is defined as part of the interface, which signifies that this class will adhere to the protocol. Looking back to the code for defining the protocol, notice that I added @required to the definition, which means that any class that adopts the protocol must implement the processComplete method (you will receive a compile warning if you don’t).

Here is the implementation of the app delegate and the required method for the protocol:

#import "TestAppDelegate.h"
#import "ClassWithProtocol.h"

@implementation TestAppDelegate

@synthesize window;

UITableViewDelegate

- (void)processSuccessful:(BOOL)success;
{
NSLog(@"Process completed");
}

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
// Create and initialize the window
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

protocolTest = [[ClassWithProtocol alloc] init];
[protocolTest setDelegate:self];
[protocolTest startSomeProcess];

[window makeKeyAndVisible];
}

- (void)dealloc
{
[window release];
[super dealloc];
}

@end

How it all works

Things goes as follows: the app delegate will create a new instance of the ClassWithProtocol object. It sets itself as the delegate and then calls the startSomeProcess method. At some point in the future, when the protocolTest object has completed its work – after the 5 second timer has fired – it will call the processSuccessful method in the app delegate to let it know it is done processing.

Simple methods for date formatting and transcoding

There is no single-line method for converting between formatting date strings and date objects in Cocoa — the API opts for flexibility rather than simplicity. Unfortunately, this combines with documentation that omits, misdirects and occasionally misinforms, making NSDateFormatter one of the more confusing classes for new Cocoa programmers. In this post, I'll try to address some of the documentation issues and I'll present some methods that will turn NSDate into a formatted string or convert between date strings in a single method.
Default, locale-based date formatting

Before I get into date formatting strings (which is the real purpose of this post) I will quickly show you how to get a string from an NSDate:

NSDate *date = [NSDate date];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
NSString *dateString = [dateFormatter stringFromDate:date];

This code formats the string according to the user's preferences set in the International General Settings (iPhone) or System Preferences (Mac OS X).

Personally, I think this is verbose for such a common activity and normally use a category method on NSDate to reduce it:

@implementation NSDate (FormattedStrings)
- (NSString *)dateStringWithStyle:(NSDateFormatterStyle)style
{
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateStyle:style];
return [dateFormatter stringFromDate:self];
}
@end

This reduces the first code sample to:

NSString *dateString = [[NSDate date] dateStringWithStyle:NSDateFormatterLongStyle];

If you need time strings instead of date strings, create a timeStringWithStyle: method by replacing the setDateStyle: invocation with setTimeStyle:.

I have read rants by other Objective-C programmers who hate seeing projects with hundreds of small categories for every little task.

Frankly, I've never understood the objection. In fact, I think lots of small categories used to choose the settings you prefer on top of common interfaces is essential for establishing consistent aesthetics for your program — your entire program will have the same style and you can easily update the aesthetic for the whole program by editing a single location.

An example would be to replace this dateStringWithStyle: method with a dateStringWithProjectStyle method that returns the appropriately configured string for use throughout your program. One of your projects might use NSDateFormatterLongStyle and the next might use a totally customized format (as I'll describe in the next sections) but you as a programmer can still invoke dateStringWithProjectStyle everywhere you need a string from an NSDate.
Date formatting documentation issues

At its heart, NSDateFormatter is very simple to use and yet it repeatedly baffles new users. I don't think this is really the fault of the API as much as the history behind it and the effect that it has had on the documentation.

Despite NSDateFormatterBehavior10_4 being the only date formatting you should ever use and the only style that should exist in the documentation, Apple's documentation has the following quirks:

1. The actual syntax for NSDateFormatterBehavior10_4 is never given in the documentation and you can easily miss the links to Unicode Standard (tr35) which describe it.
2. A majority of the pages in the date formatting documentation seem concerned with the old NSDateFormatterBehavior10_0 style formatter behavior even though this is functionally deprecated.
3. The documentation for defaultFormatterBehavior claims NSDateFormatterBehavior10_0 is the default style but it is actually NSDateFormatterBehavior10_4 in Leopard and iPhoneSDK2.0.

Then, if you've been skimming through the documentation getting confused by the different styles, you may overlook one line at the top of the NSDateFormatter API reference page:

iPhone OS Note: iPhone OS supports only the modern 10.4+ behavior. 10.0-style methods and format strings are not available on iPhone OS.

All that documentation in the iPhone SDK concerned with the old NSDateFormatterBehavior10_0 style is completely meaningless — you can't use NSDateFormatterBehavior10_0 at all on the iPhone.

Adding to the iPhone frustration, NSDateFormatterBehavior10_0 will work in the simulator, causing headaches when code suddenly stops working on the device.

On Mac OS X, even though you can use NSDateFormatterBehavior10_0, it is deprecated for all practical purposes so you probably shouldn't. Annoyingly, since the documentation still claims NSDateFormatterBehavior10_0 is the default, you should explicitly set the formatter behavior to NSDateFormatterBehavior10_4 to remain safe — at least until the documented default is updated to formally match the actual default.

I don't mean to be cruel to Apple — documentation is difficult, time consuming and annoying — but I suspect these quirks in the documentation and behavior are responsible for a lot of confusion.
Date formatting syntax

Setting a date formatting string looks like this:

NSDate *date = [NSDate date];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[dateFormatter setDateFormat:@"dd MMM, yyyy"];
NSString *dateString = [dateFormatter stringFromDate:date];

This will create a string of the format "26 May, 2009". The arrangement of data in this string is determined by the format string passed to the setDateFormat: method.

A quick summary of the date formatting options useable in this format string:
Character Matches/Outputs Multiples
y Year 1, 2 or 4 'y's will show the value, 2 digit zero-padded value or 4 digit zero-padded value respectively
M Month 1, 2, 3, 4 or 5 'M's will show the value, 2 digit zero-padded value, short name, long name or initial letter months
d Day of Month 1 or 2 'd's will show the value or 2 digit zero-padded value representation respectively.
E Weekday 1, 2, 3, 4 or 5 'e's will show the value weekday number, 2 digit zero-padded value weekday number, short name, long name or initial letter respectively. Weekday numbers starts on Sunday. Use lowercase 'e' for weekday numbers starting on Monday.
a AM or PM No repeat supported
h Hour 1 or 2 'h's will show the value or 2 digit zero-padded value representation respectively. Use uppercase for 24 hour time.
m Minute 1 or 2 'm's will show the value or 2 digit zero-padded value representation respectively.
s Second 1 or 2 's's will show the value or 2 digit zero-padded value representation respectively.
z Timezone 1, 2, 3 or 4 'z's will show short acronym, short name, long acronym, long name respectively. Use uppercase to show GMT offset instead of name — 1 or 2 digit zero-padded values shows GMT or RFC 822 respectively.

Case is important — using the wrong case can cause parsing to fail. Use lowercase by default for all values except Month.

Alphabetic and numeric characters should be enclosed in single quotes (asterisk character) if you want them to pass through the parser as literal characters. A double asterisk will pass through as a single asterisk (self escaping). Most other punctuation and spaces will go through as normal except backslash which works like a normal C-string escape character to handle tabs, newlines and other special characters.

For the complete specification, including the more obscure options that I haven't bothered to list, see Unicode Standard (tr35).
Date string transcoding

The date formatting options can also be used to parse strings. With parsing and output formatting, we can create a date string transcoder method in a category on NSDateFormatter:

+ (NSString *)dateStringFromString:(NSString *)sourceString
sourceFormat:(NSString *)sourceFormat
destinationFormat:(NSString *)destinationFormat
{
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[dateFormatter setDateFormat:sourceFormat];
NSDate *date = [dateFormatter dateFromString:sourceString];
[dateFormatter setDateFormat:destinationFormat];
return [dateFormatter stringFromDate:date];
}

We can use this method to convert one date string (for example "2007-08-11T19:30:00Z") into another ("7:30:00PM on August 11, 2007") in the following manner:

NSString *inputDateString = @"2007-08-11T19:30:00Z";
NSString *outputDateString = [NSDateFormatter
dateStringFromString:inputDateString
sourceFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"
destinationFormat:@"h:mm:ssa 'on' MMMM d, yyyy"];

Calendar stuff

The NSDateFormatter class is just for parsing and formatting strings. You shouldn't use it to build dates from their components or to decompose dates into components. For that task, use NSCalendar. It's a little outside the scope of this post but since I know it will come up, here's how to set an NSDate to the 26th of May, 2009 using NSCalendar:

NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
[components setDay:26];
[components setMonth:5];
[components setYear:2009];
NSCalendar *gregorian =
[[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDate *date = [gregorian dateFromComponents:components];

To get the components from a date, use:

unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDate *date = [NSDate date];
NSCalendar *gregorian =
[[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *components = [gregorian components:unitFlags fromDate:date];

Conclusion

As I've said a few times now, the actual API for date formatting in Cocoa is simple. The only reason why I consider it a topic worthy of a post is that I still see at least one question a week on StackOverflow and other forums asking why NSDateFormatter is failing in their code and the answer is normally because their code confuses the formatting behaviors, uses the wrong format specifiers or has otherwise misunderstood the required steps.