In part one of this tutorial we’ve seen how to display in-line date picker in a table view with dynamic cells. In this second part we are going to see how to do this for static cells. We will build a view that will add a new person to our list. I will continue from where we left off. If you don’t want to have dependencies from part one you can just create a new project with a single view and ignore the steps that configure the navigation from the people list to the add person view.
At the end of part one we had an application that displayed a list of people in a table view. When a cell is selected a UIDatePicker appeared underneath the selected cell and allowed you to change the birth date for that person.
First we need to add a button to the navigation bar of the people view controller. This button will present us with the add person view that we want to build. Go to Interface Builder and add a UIBarButtonItem. Change the identifier to be “Add”. You should see it as a + now which is what we want. We should also do some cleaning. Let’s get rid of the VCDetailViewController from Interface Builder and the .h and .m project files.
Next add a new table view controller to the storyboard. Before we start configuring this let’s create the .h and .m files for it. Go to File->New->File and create a new Objective C class. Name it VCAddPersonTableViewController and make sure it’s a UITableViewController subclass.
Once you’ve created this class go back to Interface Builder, select the table view controller, go to the Identity Inspector and set the custom class to be VCAddPersonTableViewController. We want to have some navigation options so let’s embed the table view controller in a navigation controller. Make sure that table view controller is selected then go to Editor->Embed In->Navigation Controller.
This should create a navigation controller in the storyboard and add a navigation bar to the table view controller. The add person view controller will be presented modally. We can create a segue from the add button we’ve added in the people view controller to the navigation controller that embeds the add person view controller. Just select the add button, hold Ctrl and drag from the button to the navigation controller. Select modal from the list of options for the Action Segue.
We have a way of presenting the add person view controller but we have no way out of it. We would want to release it when we finished entering details for a person or if we changed our mind about adding a new person. So let’s add two buttons to the navigation bar, one to cancel and one to save. And while we’re at it let’s also add a title to the navigation bar so we know where we are (“Add Person” should do).
We need action methods for the two buttons, so wire up cancelPressed: and savePressed: methods to the bar buttons. We can already implement the cancelPressed: method. We only want to dismiss the view controller when cancel is pressed so the method will look like this:
- (IBAction)cancelPressed:(UIBarButtonItem *)sender { [self dismissViewControllerAnimated:YES completion:nil]; }
Let’s start configuring the table view now. Select the table view and go to the Attributes Inspector tab. Make the content of the table view “Static Cells”. Because we’re using static cells we won’t need a data source for the table view so go to the Connections Inspector and remove the data source.
In part one of this tutorial we had a prototype for the date picker cell and we inserted and deleted the cell whenever we wanted to. Now let’s choose a different approach. We will always have a date picker cell and instead of deleting it and inserting it we will just show it or hide it. We can hide it by making the height of the cell 0. So let’s go to the table section and select that we need 4 rows.
The first cell of the table view will contain a UITextField that will allow the user to enter its full name. Drag a text field from the Object Library. Change its border style to none in the Attributes Inspector. We don’t need borders, we want it to look like the whole cell can be edited. Let’s create an IBOutlet for the text field called nameTextField. And we need to setup a delegate for it. We’ll make out table view controller its delegate, just Ctrl drag from the text field to the controller and select the delegate outlet. And don’t forget to go to the VCAddPersonTableViewController.h file and mark that it’s conforming to the UITextFieldDelegate protocol.
That’s great, we finished setting up the first cell. The second cell is the one that will allow you to enter a person’s birth date. Tapping on this cell will reveal the date picker. This cell will contain two labels: one with static text to indicate that the date is a birth date and one that will display the selected date. The first label will stay the same so all we need to do is set its text to “Date of birth:”. The second label will contain the value from the date picker and we will need to update this value so let’s create an outlet for it. Drag a label, position it to the right of the first label and create an outlet called birthdayLabel. This should be all the setup we need for it.
Great tutorial! Exactly what I needed.
Is this step actually necessary?
self.datePicker.hidden = NO;
self.datePicker.alpha = 0.0f;
Since we are already changing the height of the cell to 0, is there a point of actually setting the datePicker to be hiddne?
I notice that you do have a bug in there. If leave the master view with the Picker visible to go the detail view have the picker visible then save to return back now you have multiple pickers visible ..
All in all these 2 tutorials were great. If only Apple made them as this good.
When segueing away this fixes the crash. It is related to nilling out the datePickerIndexPath.row before the animation starts that solves the hiding the picker view so that you don’t have 2 pickers views when returning with detail picker viewer showing.
-(void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear: animated];
if ([self datePickerIsShown]) {
int row = self.datePickerIndexPath.row;
self.datePickerIndexPath = nil;
[self.tableView deleteRowsAtIndexPaths : @[[NSIndexPath indexPathForRow: row inSection:0]]
withRowAnimation : UITableViewRowAnimationFade];
}
}
Excellent tutorial!! Thank you!!!
I thought the “Excellent tutorials” comments are somehow fake. But THIS was the tutorial with which I get this done. It works perfectly – even with Xamarin iOS (C#). Thanks for this great tutorial!