07 - Lists
Multiple checklists 多个核对清单
The steps for this section are: 这一期的步骤是
- Add a new screen that shows all the checklists.
- 添加一个新的屏幕显示所有的清单。
- Create a screen that lets users add/edit checklists.
- 创建一个屏幕,用户可以添加/编辑清单。
- Show the to-do items that belong to a particular checklist when you tap the name of that list.
- 当你点击列表的名称时显示待办项属于一个特定的清单。
- Save all the checklists to a file and load them in again.
- 保存所有清单文件并再次加载它们。
Two new screens means two new view controllers:
- AllListsViewController shows all the user’s lists, and
- ListDetailViewController allows adding a new list and editing the name and icon of an existing list.
In AllListsViewController.swift, remove the numberOfSectionsInTableView() method. Without it, there will always be a single section in the table view.
Change the tableView(numberOfRowsInSection) method to:
Implement the tableView(cellForRowAtIndexPath) method to put some text into the cells, just so there is something to see. Note that the template already contains a commented-out version of this method. You can uncomment it by removing the /* and */ surrounding the method, and make your changes there.
In ChecklistViewController the table view used prototype cells that you designed in Interface Builder. Just for the fun of it, in AllListsViewController you are taking a different approach where you’ll create the cells in code instead.
That requires you to add the following helper method:
Select the new table view controller and set its Class in the Identity inspector to AllListsViewController.
Double-click the view controller’s navigation bar and change its title to Checklists.
Delete the empty prototype cell from the All Lists View Controller. (Simply select the Table View Cell and press delete on your keyboard.)
Ctrl-drag from the yellow circle icon at the top of All Lists View Controller into the Checklist View Controller and create a show segue.
Note that the new segue isn’t attached to any button or table view cell.
注意新的 segue 并没有与任何 button 或者 TableViewCell 关联。
In AllListsViewController.swift, add the tableView(didSelectRowAtIndexPath) method:
Putting lists into the All Lists screen
Add a new file to the project based on the Cocoa Touch Class template. Name it Checklist and make it a subclass of NSObject.
Give Checklist.swift a name property:
Add a new instance variable to AllListsViewController.swift:
In AllListsViewController.swift you could add the following init?(coder) method (don’t actually add it just yet, just read along with the description):
- Give the lists variable a value. You can also write this as lists = Array
() – that does the exact same thing. I just like the square brackets better. - Call super’s version of init?(coder). Without this, the view controller won’t be properly loaded from the storyboard. But don’t worry too much about forgetting to call super; if you don’t, Xcode gives an error message.
- Create a new Checklist object, give it a name, and add it to the array.
- Here you create three more Checklist objects. Because you declared the local variable list as var instead of let, you can re-use it.
Go to Checklist.swift and add the new init method:
Go back to AllListsViewController.swift and add init?(coder), for real this time:
Change the tableView(numberOfRowsInSection) method to return the number of objects in the new array:
Finally, change tableView(cellForRowAtIndexPath) to fill in the cells for the rows:
There are four ways that you can make table view cells: 以下有四种方式创建 TableViewCell
- Using prototype cells. This is the simplest and quickest way. You did this in ChecklistViewController. 使用原型 Cell(动态)
- Using static cells. You did this for the Add/Edit Item screen. Static cells are limited to screens where you know in advance which cells you’ll have. The big advantage with static cells is that you don’t need to provide any of the data source methods (cellForRowAtIndexPath and so on). 使用静态 Cell
- Using a nib file. A nib (also known as a XIB) is like a mini storyboard that only contains a single customized UITableViewCell object. This is very similar to using prototype cells, except that you can do it outside of a storyboard. 使用 nib 文件
- By hand, what you did above. This is how you were supposed to do it in the early days of iOS. Chances are you’ll run across code examples that do it this way, especially from older articles and books. It’s a bit more work but also offers you the most flexibility. 手工创建(开发 iOS 早期使用)
Viewing the checklists
Add a new instance variable to ChecklistViewController.swift:
Change the viewDidLoad() method in ChecklistViewController.swift to:
In AllListsViewController.swift, update tableView(didSelectRowAtIndexPath) to the following:
Add the prepareForSegue(sender) method to AllListsViewController.swift:
Adding and editing checklists
Add a new file to the project, ListDetailViewController.swift. You can either use the Cocoa Touch Class template or the Swift File template for this.
Replace the contents of ListDetailViewController.swift with:
Add the viewDidLoad() method:
Also add the viewWillAppear() method to pop up the keyboard:
Add the action methods for the Cancel and Done buttons:
Also make sure the user cannot select the table cell with the text field:
And finally, add the text field delegate method that enables or disables the Done button depending on whether the text field is empty or not.
Select the new Table View Controller (the one named “Root View Controller”) and go to the Identity inspector. Change its class to ListDetailViewController.
Change the navigation bar title from “Root View Controller” to Add Checklist.
(If double-clicking the navigation bar doesn’t work, select the Root View Controller navigation item in the outline pane and use the Attributes inspector.)
Add Cancel and Done bar button items and hook them up to the action methods in the view controller. Also connect the Done button to the doneBarButton outlet and uncheck its Enabled option.
Change the table view to Static Cells, style Grouped. You only need one cell, so remove the bottom two.
Drop a new Text Field into the cell. Here are the configuration options:
- Border Style: none
- Font size: 17
- Placeholder text: Name of the List o Adjust to Fit: disabled
- Capitalization: Sentences
- Return Key: Done
- Auto-enable Return key: check
Ctrl-drag from the view controller to the Text Field and connect it to the textField outlet.
Then Ctrl-drag the other way around, from the Text Field back to the view controller, and choose delegate under Outlets. Now the view controller is the delegate for the text field.
Connect the text field’s Did End on Exit event to the done action on the view controller.
Declare the All Lists view controller to conform to the delegate protocol by adding ListDetailViewControllerDelegate to its class line.
Also in AllListsViewController.swift, first extend prepareForSegue to:
At the bottom of the AllListsViewController.swift, implement the following delegate methods.
Also add the table view data source method that allows the user to delete checklists:
Add the tableView(accessoryButtonTappedForRowWithIndexPath) method to AllListsViewController.swift.