Hello iCoders, today I am going to be open sourcing a UITableViewCell we have created over at ELC that we have found to be very useful. When developing apps we have found that many times a form of some type is required. This is common in Registration forms, contact forms, feedback forms, etc. The problem was writing the same basic code over and over to have an elegant fast form experience for the user. To quicken the development time of these elements we created the ELCTextFieldCell class which facilitates the creation and flow of a larger form. In this post I will be walking you through the usage of the class.
GIT Hub
You can find a demo project with this code hosted on GitHub. Follow us if you find it useful, we try to open source as much as we can.
Screencast
Here is a fast video demo of a simple form that can be made using these cells.
ELCTextFieldCell Demo from Collin Ruffenach on Vimeo.
How to use
This class is best used by defining to arrays in the header of the table view controller that is going to use it. I like to call mine labels and placeholders. In these arrays store the values that are going to be the left labels for your forms cells and the placeholders for the cells. I create these in the viewDidLoad method most commonly. The reason I like to do this is because it allows for less code to be written through many other method in the table view controller. From here we need to define 6 more methods, most of which are pre defined by Apple in your table view controller class.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; }
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [labels count]; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; ELCTextfieldCell *cell = (ELCTextfieldCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[ELCTextfieldCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } [self configureCell:cell atIndexPath:indexPath]; return cell; }
Here I like to have a configureCell:AtIndexPath method to keep my delegate UITableViewCellDelegate methods a bit cleaner. In this case my 4th cell (row 3) is for a phone number, you can obviously change this depending on your needs.
- (void)configureCell:(ELCTextfieldCell *)cell atIndexPath:(NSIndexPath *)indexPath { cell.leftLabel.text = [self.labels objectAtIndex:indexPath.row]; cell.rightTextField.placeholder = [self.placeholders objectAtIndex:indexPath.row]; cell.indexPath = indexPath; cell.delegate = self; if(indexPath.row == 3) { [cell.rightTextField setKeyboardType:UIKeyboardTypeNumberPad]; } }
All that is left to do is implement the ELCTextFieldDelegate methods. The first we will implement is the method that will be called whenever text is changed within the text field of the cell. In this case I just print out all the data going through this method but in most cases you will be applying these changes to your model.
- (void)updateTextLabelAtIndexPath:(NSIndexPath*)indexPath string:(NSString*)string { NSLog(@"See input: %@ from section: %d row: %d, should update models appropriately", string, indexPath.section, indexPath.row); }
The final method that you implement will be the method called when return is hit by the user when typing in the rightTextField of the cell. Here you will first check if it is anything but the bottom most cell. If it is, you will increment the IndexPath row and then request that the rightTextField of this next cell becomes the new first responder, which will make the field active. Then you tell the tableview to make sure that this new index path cell is visible. With long forms the tableview will scroll with the users navigation through each field which is very nice. If it is indeed returning from the last cell all we do is tell the textFieldCell to resign first responder so the keyboard disappears.
-(void)textFieldDidReturnWithIndexPath:(NSIndexPath*)indexPath { if(indexPath.row < [labels count]-1) { NSIndexPath *path = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section]; [[(ELCTextfieldCell*)[self.tableView cellForRowAtIndexPath:path] rightTextField] becomeFirstResponder]; [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES]; } else { [[(ELCTextfieldCell*)[self.tableView cellForRowAtIndexPath:indexPath] rightTextField] resignFirstResponder]; } }
That’s all and you’re done! This should be a super fast way to make forms in your apps. Let me know any questions and happy iCoding.
Follow me on twitter @cruffenach