Inline date picker is an elegant way to change date, which is introduced in iOS 7. This is how it looks like in the Calendar app:
Let’s make it from scratch. Create a new Project in Xcode, and choose the iOS\Application\Single View Application templete. After creation of the project, open Main.storyboard, delete the initial view controller, drag a Table View Controller into the storyboard and make it the initial view controller. Then delete ViewController.swift in Navigator, go to File\New\File…, choose the iOS\Source\Cocoa Touch Class templete, name the class TableViewController and make it a subclass of UITableViewController. Then back to Main.storyboard, select the Table View Controller, change its class to TableViewController using the Identity Inspector (3rd tab). These are the preparatory work.
Our table view will display a list of events including their titles and time. When selecting one event, and inline date picker will appear allowing you to change the date. First, let’s define a Event class. Go to File\New\Files…, choose the iOS\Source\Swift File templete and name it Event.swift. We just need two properties, a title and a time, followed by an initializer:
Next, select the table view, set Prototype Cells to be 2 since we need two kinds of cells, one for displaying info of an event and one for displaying the date picker. Choose the style for the cell Right Detail and Custom, set the identifiers for them to be EventCell and DatePickerCell respectively. The second cell should be big enough to show the date picker properly, so set its row height (about 200 points) using the Size Inspector. Drag a Date Picker into the second cell and make them the same size using constraints.
Before showing the date picker when we select a row, we should display a list of events correctly. Since we will display the time of an event, an NSDate object, we need a date formatter to obtain a string.
We need an array property to hold some events.
Then the table view data source:
Run the app, the table view displays three events just as we expect.
But no matter which row you select by tapping, nothing happen. Now it’s time to implement showing inline date picker when you select a row. Though this is the toughest part, we have prepared anything for it, let’s continue.
When we tap a row,
tableView:didSelectRowAtIndexPath: is called. There are three cases:
- There is no date picker shown, we tap a row, then a date picker is shown just under it.
- A date picker is shown, we tap the row just above it, then the date picker is hidden.
- A date picker is shown, we tap a row that is not just above it, then the date picker is hidden and another date picker under the tapped row is shown. And there are two subcases:
- the tapped is above the shown date picker
- the tapped is under the shown date picker
Since we need to know whether a date picker is shown, and where it is, add a property to achieve these tasks:
If the date picker is hidden,
nil, else it contains the location information of the date picker. The logic of three cases is translated as below:
If the table view wants to display a date picker, a new row should be inserted, change
tableView:numberOfRowsInSection: a little:
And now there are two types of cells to display,
tableView:cellForRowAtIndexPath: should also be changed:
The height of date picker cell should be enough to show the date picker, so let’s override
If you run the app now, the date picker will be shown and hidden as you expect. But the relevant event cell won’t change the date shown on the right as you change the date of the date picker, so let’s fix this. Create an action method for the Date Picker when the value is changed:
All done. The final effect is shown below:
The demo project is here.