ToDoList Return Key Question

The user should be able to hit Return to confirm the entry in the text box.

I’ve tried a couple of solutions; both solutions end editing in the text box, but each solution has unique undesired side effects. What is the correct way to implement the Return key to end editing in the text box?

One solution is to add a Key Equivalent in MainWindowController.xib . Select the Add button. Key Equivalent is the last item in the Button Pane of the Utilities/Attributes. Click in the field and type the Return key. addItem(_:slight_smile: will now receive a message any time the user presses the Return key. Run the app and test that this works.

Undesired side effect: enter several items into the table. Select one of the items and edit it. Close editing of the item by hitting the Return key. The app will complete editing of the selected cell; the app will also message addItem(_:slight_smile: causing the method to append the text in the text field to the table as a new item.

Another solution is to connect the text field to the following action method in main window controller:

@IBAction func newText(sender: NSTextField) { if !sender.stringValue.isEmpty { self.addItem(addButton) } }

Pressing Return ends editing within the text field, sending the newText(:slight_smile: message, which newText(:slight_smile: forwards to addItem(:). addItem(:slight_smile: will append the string from the text field to the table as a new item. Once again, there is an undesired side effect. Let’s say that the user has added several items to the table. Now he wants to edit an item. He reaches for the mouse and clicks in the text field; oops, he meant to click in the cell for row 3. So he clicks in row 3. The first click opens editing in the text field. The second click finishes editing in the text field, triggering the addItem(_:slight_smile: call and an unwanted appending of the contents of the text field to the list.

As I write this, it occurs to me that a common theme here is the stale text in the text field. addItem(_:slight_smile: should clear the text field after appending its contents to the table. The method can be set up to do nothing if the text field is empty. We can configure the Add button Key Equivalent safely without worrying about an extra item being added to the table whenever we press return to finish editing an item in the table.

@IBAction func addItem(sender: NSButton) { let item = textField.stringValue if !item.isEmpty { toDoItems.append(item) tableView.reloadData() tableView.scrollRowToVisible(toDoItems.count - 1) textField.stringValue = "" // clear stale text } }
We also need to have clear the text field after inserting an item between rows.

@IBAction func insertItemBeforeSelectedRow(sender:AnyObject?) { let row = tableView.selectedRow if row > -1 { let string = textField.stringValue toDoItems.insert(string, atIndex: row) tableView.scrollRowToVisible(row) textField.stringValue = "" // clear stale text tableView.reloadData() } }

But is this the best way to handle the Return key? Thoughts?

In general my preferred path is to use the target/action on the text field to detect Return. There is a bit of a trick, which is that in Xcode you can set the text field to only send the action message on return (not when tabbing away, say): set Action to “Send on Enter Only” in the attributes inspector. Aside from that you just have to do the normal book-keeping of clearing out the field’s stringValue when appropriate.

Sheets tend to be a more appropriate context for using the Return-as-Key Equivalent path. As you found you do need to be careful about other contexts where Return might used within that window.