Update: also read Part 2 explaining a different way of solving this problem.
So a decent number of iPhone apps will not only show things like data, but also offer you the possibility to edit data. Many controls like UISlider, UISwitch and UITextfield are provided by Apple to create some type of edit screen, almost like a web form on a HTML page. Creating a simple form that only covers the top half of your screen is simple: you create your elements like UITextField at the top, and when you touch inside the field the onscreen keyboard will show up. You hit a Done Button or a non-UITextField control and the keyboard disappears again.
Now, when you have more data to add/edit than will fit in half a screen, things get more daunting:
- the keyboard should only be visible when editing a UITextField
- when touching a UITextField so that the keyboard becomes visible, it should not cover the field you are editing
- with the keyboard visible you should still be able to scroll to all elements of your editing form, and not have parts be covered indefinitely by the keyboard
Well, the most natural kind of view to use to display all controls is a UITableView. Apple uses it herself, look at the editing screen for your Mail.app settings. But when you just throw in a UITableView, you run into problems:
- when scrolling off screen, table cells are reused and therefore also its subviews like UITextFields, which causes your newly entered data to be destroyed
- when having a UITextField being firstResponder (cursor in it), you scroll it off screen and the touch inside another UITextField that then becomes firstResponder, your app will crash. This is problably because the first UITextField is destroyed before it can resignFirstResponder
So how do we do this then? Apple does use a UITableView in some way, but the above problems are show stoppers. Well the answer is: use a UITableView, but don’t let it scroll.
The trick is to nest a UITableView inside a UIScrollView. And then to give the table and the contentSize of exactly the same size that the whole form is. So if you have 10 cells each 44 pixels high, you create a UITableView with a height of 440, and put that inside a UIScrollView with a contentSize that is also 440 pixels high. This way the table is exactly the size of all the cells combined. This way no scrolling for the UITableView and therefore no reuse of cell’s with all it’s problems.
Here’s the code to set the size correctly:
// actually more object in reality
self.countries = [[NSMutableArray alloc]initWithObjects: @”Belgium”, @”Brittain”,nil];
[self.scrollView setContentSize:CGSizeMake(320, (CELL_HEIGHT * [self.countries count]))];
[self.tableView setFrame:CGRectMake(0, 0, 320, (CELL_HEIGHT * [self.countries count]))];
Well, that’s the main trick. Added to that, you want to resize the frame when the onscreen keyboard is shown and scroll the UITextField you touched in to scroll into view. Have a look at the source code to see how that’s done.