Sunday 25 September 2011

Custom Edit & Delete

Today we shall create a TableView with custom Edit & delete button. As i think the reader will be knowing how to create project.So i don't need to bug you from stretch I will start right from customizing the tableview.

As i said of customizing a delete button most of the developer run behind with function called

-(void)willTransitionTo State:(UITableViewCellStateMask)state {
[super willTransitionToState:state];
}

Through this method we can override the delete button & their properties.




Here the Question raises is when we can override the delete button why can't we override the edit button too.Yes of course, we can override the edit button too, but the apple does not entertain for this & your application can be rejected too. Hence we need to create our own edit & delete button which works similar as TableView edit & delete.







If you want to customize only delete button here is the piece of code for it.

The willTransitionToState: is a delegate of UITableViewCell which get's called when an cell is redrawn. Using this method we can play on cell UI. Here I am placing a piece of sample which contains UIImageview to show delete button.




willTransitionToState:






-(void)willTransitionToState:(UITableViewCellStateMask)state{
    [super willTransitionToState:state];
    
if((state&UITableViewCellStateShowingDeleteConfirmationMask)
==UITableViewCellStateShowingDeleteConfirmationMask)
 {        
        for (UIView *subview in self.subviews) {
            NSLog(@"class =%@",[subview class]);

 if([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellDeleteConfirmationControl"]) {             
      UIImageView *deleteBtn = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 64, 33) ];
      [deleteBtn setImage:[UIImage imageNamed:@"delete.png"]];
    [[subview.subviews objectAtIndex:0] addSubview:deleteBtn];
    [deleteBtn release];
            }//end of if
        }//end of for
      } // end of if


And if you want to customize both edit & delete button, Here is the code.

SettingCustomCell.h


@protocol SettingCustomCellDelegate 

-(void)cellObjectSetAtIndex:(int)iIndex;
@end

@interface SettingCustomCell : UITableViewCell {





    UILabel    *mCustomLabel;

    UILabel    *mContentLabel;
    UIButton  *mEditButton;
    UIButton  *mDeleteButton;
    BOOL       mIsCellEditing;
    BOOL       isEditSet;
    BOOL       mSetCellToNormalMode;
    
    id<SettingCustomCellDelegate> delegate;

}

@property(nonatomic,retain)UILabel *customLabel;
@property(nonatomic,retain)UILabel *contentLabel;
@property (nonatomic, retain) UIButton      *editButton;
@property (nonatomic, retain) UIButton      *deleteButton;
@property (nonatomic, assign) BOOL isCellEditing;
@property (nonatomic, assign)id<SettingCustomCellDelegate> delegate;
@property (nonatomic, assign) BOOL setCellToNormalMode;
@end


Here we are using Delegate for custom cell which contains label to display text, customized Edit & Delete button & some boolean variable to check the valid condition.

SettingCustomCell.m


#import "SettingCustomCell.h"

#define M_PI   3.14159265358979323846264338327950288   /* pi */

// Our conversion definition
#define DEGREES_TO_RADIANS(angle) (angle / 180.0 * M_PI)

@implementation SettingCustomCell
@synthesize customLabel=mCustomLabel;
@synthesize contentLabel= mContentLabel;
@synthesize editButton = mEditButton;
@synthesize isCellEditing = mIsCellEditing;
@synthesize deleteButton = mDeleteButton;
@synthesize  delegate;
@synthesize setCellToNormalMode =mSetCellToNormalMode;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
   
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code.
       
        if([reuseIdentifier isEqualToString:@"CellAlbum"]) {
           
            UIButton *the_button = [[UIButton alloc] init] ;//]WithFrame:CGRectMake(5, 5, 30, 30)];
             [the_button setImage:[UIImage imageNamed:@"delete2"] forState:UIControlStateNormal];
             [the_button addTarget:self action:@selector(editButtonAction:)                  forControlEvents:UIControlEventTouchUpInside];
           
            self.editButton =the_button;
            [self.contentView addSubview:the_button];
            [the_button release];
          
            UIButton *the_delete = [[UIButton alloc] init];
           [the_delete setBackgroundImage:[UIImage imageNamed:@"btn_delete_normal"] forState:UIControlStateNormal];
            [the_delete setBackgroundImage:[UIImage imageNamed:@"btn_delete_pressed"] forState:UIControlStateSelected];
             [the_delete setTitle:@"Delete" forState:UIControlStateNormal];
            [the_delete setTitle:@"Delete" forState:UIControlStateSelected];
            [the_delete addTarget:self.superview action:@selector(deleteButtonAction:) forControlEvents:UIControlEventTouchUpInside];
           
            self.deleteButton = the_delete;
            [self.contentView addSubview:the_delete];
            [the_delete release];
        }
       
       
        UILabel* the_CustomLabel = [[UILabel alloc]init];//WithFrame:CGRectMake(5, 5, 170,20)];
        the_CustomLabel.backgroundColor=[UIColor clearColor];
        the_CustomLabel.font=[UIFont fontWithName:@"Helvetica-Bold" size:16];
        //the_CustomLabel.textColor = [UIColor whiteColor];
        [self.contentView addSubview:the_CustomLabel];
        self.customLabel = the_CustomLabel;
        [the_CustomLabel release];
       
       
        UILabel* the_ContentLabel = [[UILabel alloc]init];//WithFrame:CGRectMake(5, 25, 170, 18)];
        the_ContentLabel.backgroundColor=[UIColor clearColor];
         the_ContentLabel.font=[UIFont fontWithName:@"Helvetica-Bold" size:12];
        //the_ContentLabel.textColor = [UIColor whiteColor];
        [self.contentView addSubview:the_ContentLabel];
        self.contentLabel = the_ContentLabel;
        [the_ContentLabel release];
    }
    return self;
}


- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];
    }

-(void)layoutSubviews {
    [super layoutSubviews];
   
    if(self.isCellEditing ) {
        if(self.setCellToNormalMode) {
            [self.editButton setFrame:CGRectMake(5, 5, 30, 30)];
            [self.contentLabel setFrame:CGRectMake(40, 25, 170, 18)];
            [self.customLabel setFrame:CGRectMake(40, 5, 170, 20)];
       
            [UIView beginAnimations:nil context:NULL];
            [UIView setAnimationDuration:0.20f];
            [UIView setAnimationCurve:UIViewAnimationCurveLinear];
            [UIView setAnimationBeginsFromCurrentState:YES];
            CGAffineTransform transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0));
            self.editButton.transform = transform;
            [self.deleteButton setFrame:CGRectMake(322, 5, 57, 30)];
            [UIView commitAnimations];
                       
        }
       
        else {

            [UIView beginAnimations:nil context:NULL];
            [UIView setAnimationDuration:0.20f];
            [UIView setAnimationCurve:UIViewAnimationCurveLinear];
            [UIView setAnimationBeginsFromCurrentState:YES];
            [self.editButton setFrame:CGRectMake(5, 5, 30, 30)];
            [self.contentLabel setFrame:CGRectMake(40, 25, 170, 18)];
            [self.customLabel setFrame:CGRectMake(40, 5, 170, 20)];
            //[self.deleteButton setFrame:CGRectMake(230, 5, 90, 30)];
            [UIView commitAnimations];
        }
        isEditSet = YES;
        }
    else {
       
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.00f];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [self.editButton setFrame:CGRectMake(-40, 5, 30, 30)];
        [self.contentLabel setFrame:CGRectMake(10, 25, 170, 18)];
        [self.customLabel setFrame:CGRectMake(10, 5, 170, 20)];
        [self.deleteButton setFrame:CGRectMake(322, 5, 57, 30)];
        [UIView commitAnimations];
        isEditSet = NO;
    }
}

- (void)dealloc {
    self.customLabel = nil;
    self.contentLabel = nil;
    self.editButton = nil;
    self.deleteButton = nil;
    self.isCellEditing = 0;
    self.delegate = nil;
[super dealloc];
}


-(void)editButtonAction:(id)sender {
    UIButton *resultButton = (UIButton *)sender;
    if(isEditSet) {
        [delegate cellObjectSetAtIndex:[sender tag]];
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.30f];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        [UIView setAnimationBeginsFromCurrentState:YES];       
       
        CGAffineTransform transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(90));
        resultButton.transform = transform;
        [self.deleteButton setFrame:CGRectMake(230, 5, 57, 30)];
       [UIView commitAnimations];
        [self.accessoryView setHidden:YES];
        isEditSet =NO;
       }
   
    else {
       
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.30f];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        [UIView setAnimationBeginsFromCurrentState:YES];
        CGAffineTransform transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0));
        resultButton.transform = transform;
        [self.deleteButton setFrame:CGRectMake(322, 5, 57, 30)];
        [UIView commitAnimations];
        [self.accessoryView setHidden:NO];
       isEditSet = YES;
    }
   
}
@end

--------------------------------------------end of Custom cell-------------------------------------------------------



#import <UIKit/UIKit.h>
#import "SettingCustomCell.h"
@interface custom_edit_tableViewController : UIViewController<SettingCustomCellDelegate> {
    UIBarButtonItem *rightBarButton;
    UITableView        *editTableView;
    BOOL isTableEditing;
    int indexNumber;
    NSMutableArray *alarmArray;
}
@property (nonatomic, retain) IBOutlet UIBarButtonItem *rightBarButton;
@property (nonatomic,retain) IBOutlet UITableView    *editTableView;
-(IBAction)editButton:(id)sender;
@end

--------------------------------------------------------------------------------------------------------------------------



#import "custom_edit_tableViewController.h"

@implementation custom_edit_tableViewController
@synthesize editTableView;
@synthesize rightBarButton;

- (void)viewDidLoad {
    [super viewDidLoad];
       isTableEditing = NO;
    indexNumber = -1;
    alarmArray = [[NSMutableArray alloc]initWithObjects:@"Apple",@"Mac",@"iMac",@"iPhone",@"iPod",@"iPad",@"Mac Book",nil];

    //UIBarButtonItem *right = self.navigationController.navigationItem.rightBarButtonItem;
    NSLog(@"frame =%f",self.navigationController.navigationItem.rightBarButtonItem.width);
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    self.rightBarButton =nil;
    self.editTableView = nil;
}
- (void)dealloc {
    self.rightBarButton =nil;
    self.editTableView = nil;
    [super dealloc];
}

-(IBAction)editButton:(id)sender{
    UIBarButtonItem *barItem = (UIBarButtonItem *)sender;
        if([[barItem title] isEqualToString:@"Edit"]){
        [barItem setTitle:@"Done"];
        isTableEditing = YES;
        [self.editTableView reloadData];
        }
    else {
        [barItem setTitle:@"Edit"];
         isTableEditing = NO;
        [self.editTableView reloadData];
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{return [alarmArray count];}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"CellAlbum";
    SettingCustomCell *cell = (SettingCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[SettingCustomCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
        cell.delegate = nil;
        cell.delegate = self;
    }
   if(isTableEditing)
    {cell.isCellEditing = NO;
       
        //Anand Kumar
        /*Description:  To perfrom Edit & Delete Action uncomment the below code
        */
        cell.isCellEditing = YES;
        if(indexNumber == indexPath.row) {
            cell.setCellToNormalMode = YES;
            }
        else {
            cell.setCellToNormalMode = NO;
            }      
    }
    else {       
        cell.isCellEditing = NO;
       [cell setEditing:NO];
    }
    [cell.editButton setTag:indexPath.row];
    [cell.deleteButton setTag:indexPath.row+100];
   [cell.customLabel setText:[alarmArray objectAtIndex:indexPath.row]];
    [cell.contentLabel setText:@"abc"];
    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
    return cell;
}
-(void)deleteButtonAction:(id)sender {
    NSLog(@"delete row at index =%d",[sender tag]-100);
}

-(void)cellObjectSetAtIndex:(int)iIndex {
   
    if(indexNumber > -1 && indexNumber != iIndex) {
        NSIndexPath* updatePath = [NSIndexPath indexPathForRow:indexNumber inSection: 0];
        [self.editTableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:updatePath,nil] withRowAnimation:UITableViewRowAnimationNone];
      }
    indexNumber = iIndex;
   }

@end

-------------------------------------------------------------------------------------------------------------------------




Here is the source code link & this link for reference 

More book on Objective-c

NSPredicate with Object

Cocoa-Touch ships with an super-useful class that will help you search through your lists of objects just like they were coming from a database. The class is called NSPredicate which also works with Core Data. This is very powerful stuff, especially what you are working with data intensive applications.

Here Is How NSPredicate Works

First off, keep in mind that generally we are using NSArray to manage lists of objects in our apps. The objects that NSArray stores for us are made up of properties like name, length and whatever is required for the objects in question. NSPredicate works by defining queries that select objects from an array based on the properties of the objects in the array.
Here are the steps required to search arrays with NSPredicate:

Find or create an NSArray full of objects with interesting properties
Create an NSPredicate object with the search query that you want to use
You can use this NSPredicate object to either filter the array or create a new array with a subset of data

Essentially, these three steps are all it takes to filter an array. Of course, you will need some other pieces in place to do some meaningful work. Next, I will show you a concrete example of using NSPredicate with a custom class.

NSPredicate Search Example

Here Is The Type Of Object We Will Query

The first thing I did for this example was to create a custom class called Predicate_Data that could correspond to an individual row of data in a database.


Anyway, here is the class definition for Predicate_Data:

#import <Foundation/Foundation.h>

@interface Predicate_Data : NSObject {
    int primaryKey;
    NSString *name;
    NSNumber *rollNo;
}

@property(nonatomic, assign) int primaryKey;
@property(nonatomic, retain) NSString *name;
@property(nonatomic, retain) NSNumber *rollNo;

@end



Create Your NSArray & Fill It With Predicate_Data Objects

In effect, we are creating a list of objects that is a bit like a database table. Note here that listOfItems is declared as an NSMutableArray at the top of the file where this code would be located since it needs to stay in scope though-out the lifecycle of objects made from the class:
listOfItems = [[NSMutableArray alloc] init];

for(int i=0;i< 5;i++)
{
Predicate_Data *the_object = [[Predicate_Data alloc]init];
the_object.primaryKey = i;
the_object.name  = [NSString stringWithFormat:@"String%d",i];
the_object.rollNo = [NSNumber numberWithString:@"3102%d",i]; 
[listOfItems addObject:the_object];

[the_object release];
 
}

To summarize, we create an array and then create each object and add each object to the array. Here is what the results would look like if we were to present this array in a table view:

Get A Subset Of Data Instead!

So here is what you have been waiting for. To display a subset of the dataset you would need to code an NSPredicate using a query string. For instance, if we wanted to find out who in our dataset were programmers we could do something like this:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'String1'"];
[listOfItems filterUsingPredicate:predicate];


All you need to do is create the NSPredicate with our query and send the filterUsingPredicate message to your array using the NSPredicate object as an argument. If we tack this query to the end of our code and again run an app using a table view it would look like this:

 NSPredicate Query Examples:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"rollNo >= 31021"];
[listOfItems filterUsingPredicate:predicate];


Find everyone who has a name that begins with “T”:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH 'T'"];
[listOfItems filterUsingPredicate:predicate];


Other few examples on NSPredicate

Simple match

The simplest example is when you just need an exact match against a single value. This is a fairly meaningless example in this case but illustrates the basic technique:

    NSString *match = @"Kumar.";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF == %@", match];
    NSArray *results = [directoryContents filteredArrayUsingPredicate:predicate];


The query string is simply “SELF == %@” where SELF refers to the each element in the array. To use the predicate we apply it to the array of file names using filterArrayUsingPredicate:. In this trivial (and pointless) example the results array would contain a single string “Kumar.” assuming that file existed in the directory.

Wildcard match

To match using a wildcard string the query can use like instead of the comparison operator and include the “*”  (match zero or more characters) or “?” (match exactly 1 character) as wildcards as follows:
    NSString *match = @"Anand*.";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF like %@", match];
    NSArray *results = [directoryContents filteredArrayUsingPredicate:predicate];



In this case the results array would contain the filenames that match Anand*. (e.g. Anand-001., Anand-002., etc.).





Wednesday 10 August 2011

TableView with Textfield


Today we are going to know how to use textfield in an tableview.Most of you may be knowing it but here I am going to explain most easiest and tricky way.


First let us create a new project by some name.



@interface SBSpeakerCustomCell : UITableViewCell {
UILabel *mLabel;
UITextField *mTextField;
}
@property (nonatomic, retain)UILabel *mLabel;
@property (nonatomic, retain)UITextField *mTextField;
@end


#import "SBSpeakerCustomCell.h"

@implementation SBSpeakerCustomCell
@synthesize mLabel,mTextField;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.

mLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 5, 100, 35)];
[mLabel setTextAlignment:UITextAlignmentRight];
[mLabel setBackgroundColor:[UIColor clearColor]];

[self addSubview:mLabel];

mTextField = [[UITextField alloc] initWithFrame:CGRectMake(mLabel.frame.origin.x + mLabel.frame.size.width+2, 5, self.frame.size.width - (mLabel.frame.size.width+mLabel.frame.origin.x)- 15, 35)];
[mTextField setBackgroundColor:[UIColor clearColor]];
[self addSubview:mTextField];
}
return self;
}

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

[super setSelected:selected animated:animated];

// Configure the view for the selected state.
}

- (void)dealloc {
[mLabel release];
[mTextField release];

[super dealloc];
}

@end


Here I have use TableViewWithTextFieldViewController for this example.

@interface TableViewWithTextFieldViewController : UIViewController {


NSMutableArray *mArrayList;

BOOL isEditMode;

int numberOfSectionPerRow;

NSMutableArray *mArray;

NSMutableArray *mDetailslist;

int count;
}
@end



Here I am using 3 array for different reason don't worry about it, we will concentrate only on how we are using textfield in tableview.

As you can notice I have used custom cell for the textfield. Copy & paste the code as it is.

#import "TableViewWithTextFieldViewController.h"

#import "SBSpeakerCustomCell.h"
#define kNavigationBar 104
@implementation TableViewWithTextFieldViewController


- (void)loadView {

UIView *mainView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];

[mainView setBackgroundColor:[UIColor clearColor]];

self.view = mainView;

[self.navigationController.navigationBar setHidden:NO];

UINavigationBar *theNavigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];

[theNavigationBar setTintColor:[UIColor colorWithRed:0.4039216041564941 green:0.6470588445663452 blue:0.062745101749897 alpha:1]];

UINavigationItem *theNavigationItem = [[UINavigationItem alloc] init];

theNavigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Edit" style:UIBarButtonItemStylePlain target:self action:@selector(EditAction:)];

[theNavigationBar setItems:[NSArray arrayWithObjects:theNavigationItem,nil]];

[theNavigationBar setTag:kNavigationBar];

[self.view addSubview:theNavigationBar];

[theNavigationItem release];

[theNavigationBar release];

UITableView *speakerTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 40, self.view.frame.size.width, self.view.frame.size.height+ 40) style:UITableViewStyleGrouped];

speakerTable.delegate = self;

speakerTable.dataSource = self;

speakerTable.tag = 103;

[self.view addSubview:speakerTable];

[speakerTable release];

isEditMode = NO;

mArray = [[NSMutableArray alloc]initWithObjects:@"Bedroom",@"Cabinet",@"Bathroom",@"Hall",@"Mobile",@"Balcony",@"Others",nil];

mDetailslist = [[NSMutableArray alloc] initWithObjects:@"",@"",@"",@"",@"",@"",@"",nil];

count =0;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
count = 0;

return 2;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

//if table is in editing mode return number of rows equivalent to number of items
if(section == 0)
numberOfSectionPerRow =5;

else 
numberOfSectionPerRow =2;


return numberOfSectionPerRow;
}

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

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];

}
int section1;

if(indexPath.section == 1)
section1 = 5;
else
section1 = 0;

int row =section1 + indexPath.row;


cell.textLabel.text=[NSString stringWithFormat:@"%@ : %@",[mArray objectAtIndex:row],[mDetailslist objectAtIndex:row]];

[cell.textLabel setTextAlignment:UITextAlignmentRight];

cell.textLabel.backgroundColor = [UIColor clearColor] ; 

cell.detailTextLabel.backgroundColor = [UIColor clearColor] ;

count++;

return cell;

}

else {

static NSString *CellIdentifier = @"Cell1";

SBSpeakerCustomCell *cell =(SBSpeakerCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[SBSpeakerCustomCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];

}

[cell.mTextField setTag:(indexPath.section *10)+ indexPath.row];//(indexPath.section *10)+ indexPath.row

cell.mTextField.delegate = self;

int section1;

if(indexPath.section == 1)
section1 = 5;
else
section1 = 0;

int row =section1 + indexPath.row;


[cell.mLabel setText:[NSString stringWithFormat:@"%@ : ",[mArray objectAtIndex:row]]];
[cell.mTextField setText:[mDetailslist objectAtIndex:row]];

count++;

return cell;
}

}



Whenever an Edit button is pressed I am animating the table and reloading it.



-(void)EditAction:(id)sender {


UINavigationBar *theNavigationBar = (UINavigationBar *) [self.view viewWithTag:kNavigationBar];

if(!isEditMode)
[[theNavigationBar topItem] setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStylePlain target:self action:@selector(DoneAction:)]];

UITableView *speakerTable = (UITableView *) [self.view viewWithTag:103];

isEditMode = YES;

for (int i=0 ;i < numberOfSectionPerRow ; i++) {

[speakerTable beginUpdates]; [speakerTable deleteSections:[NSIndexSet indexSetWithIndex:i ] withRowAnimation:UITableViewRowAnimationBottom];

[speakerTable insertSections:[NSIndexSet indexSetWithIndex:i ] withRowAnimation:UITableViewRowAnimationBottom]; 

[speakerTable endUpdates]; 
}

-(void)DoneAction:(id)sender {
UINavigationBar *theNavigationBar = (UINavigationBar *) [self.view viewWithTag:kNavigationBar];

if(isEditMode){ 
[[theNavigationBar topItem] setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:@"Edit" style:UIBarButtonItemStylePlain target:self action:@selector(EditAction:)]];
}

UITableView *speakerTable = (UITableView *) [self.view viewWithTag:103]; 
isEditMode = NO;

for (int i=0 ;i < numberOfSectionPerRow ; i++) {

[speakerTable beginUpdates]; 

[speakerTable deleteSections:[NSIndexSet indexSetWithIndex:i ] withRowAnimation:UITableViewRowAnimationBottom]; 

[speakerTable insertSections:[NSIndexSet indexSetWithIndex:i ] withRowAnimation:UITableViewRowAnimationBottom]; [speakerTable endUpdates]; 

[speakerTable setFrame:CGRectMake(0, 40, self.view.frame.size.width, self.view.frame.size.height+ 40)];

NOTE: Here I am going to explain how to scroll the table as and when we switch to next textfield.As you know that keyboard is an event which differ from tableview events. You can try without using below logic and find the difference. Did you find any difference or problem without using below logic. Let me explain you briefly if you have not understood. Once you press on Edit button table get's animate & return into edit mode, Where we find the textFields in the Tableview. Now comes the play when you tap on any textfield within the cell and try to switch to another the textfield by pressing TAB or retrun it cursor move to the next textfield but the tableview will not scroll and the textfield is behind the keyboard which cannot be visible to the user. Now copy below code and run it.


- (void)textFieldDidBeginEditing:(UITextField *)textField {
int row = [textField tag]%10;
int section = [textField tag] /10;

UITableView *speakerTable = (UITableView *) [self.view viewWithTag:103]; [speakerTable setFrame:CGRectMake(0, 40, self.view.frame.size.width, 210)]; 

NSIndexPath *indPath = [NSIndexPath indexPathForRow:row inSection:section];
[speakerTable scrollToRowAtIndexPath:indPath atScrollPosition:UITableViewScrollPositionTop animated:YES];

- (void)textFieldDidEndEditing:(UITextField *)textField{ 

int row = [textField tag] %10; int section = [textField tag] /10; int index = 0; if(section >= 1)

index = 5;

index = index + row;

[mDetailslist insertObject:[textField text] atIndex:index];

}

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{

UITableView *speakerTable = (UITableView *) [self.view viewWithTag:103];

[textField resignFirstResponder];

[speakerTable setFrame:CGRectMake(0, 40, self.view.frame.size.width, self.view.frame.size.height+ 40)];

return YES;
}

Did you see the difference the table was scrolling to the top of view which can be visible & it not getting hidden behind the keyboard.

- (void)dealloc {

[mArray release];

[mDetailslist release];

[super dealloc];
}

@end

Did you enjoyed it.Please post comments on this post. :)

Download the code Here.

Friday 13 May 2011

Push Notification Services

Programming Push Notification Services

one of the drawback of the iphone is running an application in the background when the user switches to another application. So, application will not to receive timely updates at constant state of connectivity.

To remedy this limitation, Apple released the Apple Push Notification Service (APNs). The APNs is a service that allows your device to be constantly connected to Apple's push notification server. When you want to send a push notification to an application installed on the users' devices, you (the provider) can contact the APNs so that it can deliver a push message to the particular application installed on the intended device.
In this article, you will learn how to perform the various steps needed to create an iPhone application that uses the APNs.

Generating a Certificate Request

The first step to using the APNs is to generate a certificate request file so that you can use it to request for a development SSL certificate later on.

1. Launch the Keychain Access application in your Mac OS X.
2. Select Keychain Access'Certificate Assistant'Request a Certificate From a Certificate Authority
(see Figure 1):


 3. Enter the information required and check the Saved to disk option. Click Continue (see Figure 2).


 4. Save the certificate request using the suggested name and click Save (see Figure 3):
 Click Done in the next screen.


Creating an App ID

Each iPhone applications that uses the APNs must have a unique application ID that uniquely identifies itself. In this step, you will learn how to create an App ID for push notification.

1. Sign in to the iPhone Developer Program at: http://developer.apple.com/iphone/. Click on the iPhone Developer Program Portal on the right of the page (see Figure 4).

 2. You should see the welcome page (see Figure 5).

3. Click on the App IDs tab on the left and then click on the New App ID button (see Figure 6).

4. Enter "PushAppID" for the Description and select Generate New for the Bundle Seed ID. For the Bundle Identifier, enter net.learn2develop.MyPushApp. Click Submit (see Figure 7).


5. You should now see the App ID that you have created (together with those you have previously created) (see Figure 8).




Configuring an App ID for Push Notifications

Once an App ID is created, you need to configure it for push notifications.
1. To configure an App ID for push notification, you need to click the Configure link displayed to the right of the App ID. You will now see the option (see Figure 9).


 

Check the Enable for Apple Push Notification service option and click the Configure button displayed to the right of the Development Push SSL Certificate.
2. You will now see the Apple Push Notification service SSL Certificate Assistant screen. Click Continue (see Figure 10).




3. Click the Choose File button to locate the Certificate Request file that you have saved earlier. Click Generate (see Figure 11).

4. Your SSL Certificate will now be generated. Click Continue (see Figure 12).

5. Click the Download Now button to download the SSL Certificate. Click Done (see Figure 13).

6. The SSL Certificate that you download is named aps.developer.identity.cer. Double-click on it to install it in the Keychain Access application (see Figure 14). The SSL certificate will be used by your provider application so that it can contact the APNs to send push notifications to your applications.

Creating a Provisioning Profile

The next step is to create a provisioning profile so that your application can be installed onto a real device.
1. Back in the iPhone Development Program Portal, click on the Provisioning tab and click on the New Profile button (see Figure 15).
2. Type in MyDevicesProfile as the profile name. Select PushAppID as the App ID. Finally, check all the devices that you want to provision (you can register these devices with the iPhone Developer Program Portal through the Devices tab). Click Submit (see Figure 16).

3. The provisioning profile will now be pending approval. After a while, you will see it appear. Click on the Download button to download the provisioning profile (see Figure 17).

4. The downloaded provisioning profile is named MyDevicesProfile.mobileprovision.

Provisioning a Device

With the provision profile created, you will now install it onto a real device.
1. Connect your iPhone or iPod Touch to your Mac.
2. Drag and drop the downloaded MyDevicesProfile.mobileprovision file onto the Xcode icon on the Dock.
3. Launch the Organizer application from within Xcode and select the device currently connected to your Mac. You should see the MyDevicesProfile installed on the device (see Figure 18).

Creating the iPhone Application

1. In Xcode, create a new View-Based Application project and name it as ApplePushNotification.
2. Drag and drop a WAV file (shown as beep.wav in this example) onto the Resources folder in Xcode (see Figure 19).



 3. Expand on the Targets item in Xcode and select the ApplePushNotification item. Press Command-I. In the Info window, click the Properties tab (see Figure 20).



In the Identifier textbox, type <net.learn2develop.MyPushApp.
4. Click on the Build tab and type "Code Signing" in the search box. In the Any iPhone OS Device item, select the profile as shown in Figure 21:
5. In the ApplePushNotificationAppDelegate.m file, type the following code in bold:

#import "ApplePushNotificationAppDelegate.h"
#import "ApplePushNotificationViewController.h"
 
@implementation ApplePushNotificationAppDelegate
 
@synthesize window;
@synthesize viewController;
 
- (void)applicationDidFinishLaunching:(UIApplication *)application {    
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
 
    NSLog(@"Registering for push notifications...");    
    [[UIApplication sharedApplication] 
        registerForRemoteNotificationTypes:
        (UIRemoteNotificationTypeAlert | 
         UIRemoteNotificationTypeBadge | 
         UIRemoteNotificationTypeSound)];
 
}
 
- (void)application:(UIApplication *)app
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 
 
    NSString *str = [NSString 
        stringWithFormat:@"Device Token=%@",deviceToken];
    NSLog(str);
 
}
 
- (void)application:(UIApplication *)app 
didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 
 
    NSString *str = [NSString stringWithFormat: @"Error: %@", err];
    NSLog(str);    
 
}
 
- (void)application:(UIApplication *)application 
didReceiveRemoteNotification:(NSDictionary *)userInfo {
 
    for (id key in userInfo) {
        NSLog(@"key: %@, value: %@", key, [userInfo objectForKey:key]);
    }    
 
}
 
- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}
 
@end
 
6.Press Command-R to test the application on a real device.
Press Shift-Command-R
 in Xcode to display the Debugger Console window. Observe carefully the 
device token that is printed (see Figure 22). In the figure below, the 
token is: 38c866dd bb323b39 ffa73487 5e157ee5 a85e0b7c e90d56e9 fe145bcc 6c2c594b.
Record down this device token (you might want to cut and paste it into a text file).  

7. If you go to the Settings application on your iPhone/iPod Touch, you will notice that you now have the Notifications item (see Figure 23).

Creating the Push Notification Provider

A Push Notification provider is an application written by the application's developer to send push notifications to the iPhone application through the APNs.
Here are the basic steps to send push notifications to your applications via the Apple Push Notification Service (APNs):
1. Communicate with the APNs using the SSL certificate you have created earlier.
2. Construct the payload for the message you want to send.
3. Send the push notification containing the payload to the APNs.
The APNs is a stream TCP socket that your provider can communicate using a SSL secured communication channel. You send the push notification (containing the payload) as a binary stream. Once connected to the APNs, you should maintain the connection and send as many push notifications as you want within the duration of the connection.
Tip: Refrain from opening and closing the connections to the APNs for each push notification that you want to send. Rapid opening and closing of connections to the APNs will be deemed as a Denial-of-Service (DOS) attack and may prevent your provider from sending push notifications to your applications.
The format of a push notification message looks like Figure 24 (figure from Apple's documentation):

For more details, please refer to Apple Push Notification Service Programming Guide.
The payload is a JSON formatted string (maximum 256 bytes) carrying the information you want to send to your application. An example of a payload looks like this:

{
    "aps": { 
        "alert" : "You got a new message!" ,
        "badge" : 5, 
        "sound" : "beep.wav"},
     "acme1" : "bar", 
     "acme2" : 42
}
 
To save yourself the trouble in developing a push notification provider from scratch, you can use the PushMeBaby application (for Mac OS X) written by Stefan Hafeneger .

1. Open the PushMeBaby application in Xcode.
2. Right-click on the Resources folder in Xcode and select Add Existing Files…. Select the aps.developer.identity.cer file that you have downloaded earlier (see Figure 25).


 
3.In the ApplicationDelegate.m file, modify the code as shown in bold below: 
 
- (id)init {
    self = [super init];
    if(self != nil) {
        self.deviceToken = 
@"38c866dd bb323b39 ffa73487 5e157ee5 a85e0b7c e90d56e9 fe145bcc 6c2c594b";
 
        self.payload = 
@"{\"aps\":{\"alert\":\"You got a new message!\",\"badge\":5,\"sound\":\"beep.wav\"}
,\"acme1\":\"bar\",\"acme2\":42}";
 
        self.certificate = [[NSBundle mainBundle] 
            pathForResource:@"aps_developer_identity" ofType:@"cer"];
    }
    return self;
}
 
4.Press Command-R to test the application. You will be
 asked to grant access to the certificate. Click Always Allow (see 
Figure 26): 
 
 


 On the iPhone/iPod Touch, ensure that the ApplePushNotification application is not running. To send a message to the device, click the Push button. The server essentially sends the following message to the Apple Push Notification server:

{
    "aps": { 
        "alert" : "You got a new message!" ,
        "badge" : 5, 
        "sound" : "beep.wav"},
     "acme1" : "bar", 
     "acme2" : 42
}
 
5.If the message is pushed correctly, you should see the notification as shown in Figure 27. 



6. If you now debug the ApplePushNotification application by pressing Command-R and send a push message from the PushMeBaby application, the Debugger Console window will display the following outputs:

2009-11-24 21:11:49.182 ApplePushNotification[1461:207] key: acme1, value: bar
2009-11-24 21:11:49.187 ApplePushNotification[1461:207] key: aps, value: {
    alert = "You got a new message!";
    badge = 5;
    sound = "beep.wav";
}
2009-11-24 21:11:49.191 ApplePushNotification[1461:207] key: acme2, value: 42