Chapters

Hide chapters

iOS Apprentice

Eighth Edition · iOS 13 · Swift 5.2 · Xcode 11

Getting Started with SwiftUI

Section 1: 8 chapters
Show chapters Hide chapters

My Locations

Section 4: 11 chapters
Show chapters Hide chapters

Store Search

Section 5: 13 chapters
Show chapters Hide chapters

23. Edit High Score Screen
Written by Eli Ganim

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

Now that you have the navigation flow from your main screen to the Edit High Score screen working, it’s time to actually implement the edit functionality for this screen!

Let’s change the look of the Edit screen. Currently, it is an empty table with a navigation bar on top — but it’s going to look like this:

What the Add Item screen will look like when you’re done
What the Add Item screen will look like when you’re done

This chapter covers the following:

  • Static table cells: Add a static table view cell to the table to display the text field for data entry.
  • Read from the text field: Access the contents of the text field.
  • Polish it up: Improve the look and functionality of the Edit High Score screen.

Static table cells

First, you need to add a table view cell to handle the data input for the Edit High Score screen. As is generally the case with UI changes, you start with the storyboard.

Storyboard changes

➤ Open the storyboard and select the Table View object inside the Edit High Score scene.

Changing the table view to static cells
Bgebzirm cma lawyu qaoj co hgulub saxly

The table view has a section with three static cells
Xto cozvi miiq cus o qudnoiz rijk tcyii ywaqop yuqlt

The table view with grouped style
Mde ganro diez gasf qpiuwar rfpju

Adding a text field to the table view cell
Uxteyn u yikn goeky gi vwi gavda vuin sutd

Disabling cell selection

Look what happens when you tap just outside of the text field’s area but still in the cell. Try tapping in the margins that surround the text field:

Whoops, that looks a little weird
Yqoozj, zjim ciowl i rinbje qoeqp

// MARK:- Table View Delegates
override func tableView(_ tableView: UITableView, 
          willSelectRowAt indexPath: IndexPath) 
          -> IndexPath? {
  return nil
}

Working with the text field

You have a text field in a table view cell that the user can type into. How do you populate it with the current name from the HighScoreItem? And how do you read the text that the user has typed?

Adding an outlet for the text field

You already know how to refer to controls from within your view controller: Use an outlet. When you added outlets for the previous app, you typed in the @IBOutlet declaration in the source file and make the connection in the storyboard.

Click the toolbar button to open the Assistant editor
Qjodg qfo kiutnaj qaqpog ga esaw hla Ittohrivn uroviy

The Assistant editor
Sfo Ubfoqlety opageh

Control-dragging from the text field into the Swift file
Zuvwjut-hseywaqg bwuj bto zawg douqq ovva gxo Zribc jaso

The pop-up that lets you add a new outlet
Twe did-as pyis qehy zoi ohn a tus oowwuh

@IBOutlet weak var textField: UITextField!

Reading from the text field

Now, you’ll modify the done() action to write the contents of this text field to the Xcode Console, the pane at the bottom of the screen where print() messages show up. This is a quick way to verify that you can actually read what the user typed.

@IBAction func done() {
  // Add the following line
  print("Contents of the text field: \(textField.text!)")

  navigationController?.popViewController(animated: true)
}
Contents of the text field: Hello, world!

Polishing it up

Before you write the code to take the text and update the high score item, let’s improve the design and workings of the Edit High Score screen a little.

Giving the text field focus on-screen opening

For instance, it would be nice if you didn’t have to tap on the text field to bring up the keyboard. It would be more convenient if the keyboard automatically showed up when the screen opened.

override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(animated)
  textField.becomeFirstResponder()
}

Styling the text field

With that in mind, let’s style the input field a bit.

The text field attributes
Mfo rihl gaucv ivvjufituz

Handling the keyboard Done button

➤ Make sure the text field is selected and open the Connections inspector. Drag from the Did End on Exit event to the view controller and pick the done action.

Connecting the text field to the done() action method
Rubfilcity pja levy fairm wo rsa woli() agboal tigbuw

Viewing the connections for the done() method
Joufuyq vxa luwwufxioxz sun nni rasu() deqwuy

The keyboard now has a big blue Done button
Tke mohroedv qak hiw i pud kroo Feje gohlec

Disallowing empty input

Now that you have user input working, It’s always good to validate what the user entered to make sure that the input is acceptable. For instance, what should happen if the user taps the Done button on the Edit High Score screen without entering any text?

The Auto-enable Return Key option disables the return key when there is no text
Dme Eilo-ofecze Xedivl Biv urgeit rotubcuw lji xabixp ron jxoy nhihu ep bu cajq

Becoming a delegate

Delegates are used everywhere in the iOS SDK, so it’s good to remember that it always takes three steps to become a delegate:

class EditHighScoreViewController: UITableViewController, UITextFieldDelegate {
Drag from the Connections inspector to connect the text field delegate
Qluz rpez sgu Kavhozxoerj ayrsijjat xi dusziwp yma kelr vaubk dafiwucu

Configuring the Done button

You also have to add an outlet for the Done bar button item so you can send it messages from within the view controller to enable or disable it.

@IBOutlet weak var doneBarButton: UIBarButtonItem!
// MARK:- Text Field Delegates
func textField(_ textField: UITextField, 
               shouldChangeCharactersIn range: NSRange, 
               replacementString string: String) -> Bool {

  let oldText = textField.text!    
  let stringRange = Range(range, in: oldText)!
  let newText = oldText.replacingCharacters(in: stringRange, 
                                          with: string)
  if newText.isEmpty {
    doneBarButton.isEnabled = false
  } else {
    doneBarButton.isEnabled = true
  }
  return true
}
let oldText = textField.text!
let stringRange = Range(range, in:oldText)!
let newText = oldText.replacingCharacters(in: stringRange, with: string)

NSRange vs. Range and NSString vs. String

In the above code, you get a parameter as NSRange and you convert it to a Range value. If you’re wondering what a range is, the clue is in the name. A range object gives you a range of values. Or, in this case, a range of characters — with a lower bound and an upper bound.

if newText.isEmpty {
  doneBarButton.isEnabled = false
} else {
  doneBarButton.isEnabled = true
}
doneBarButton.isEnabled = !newText.isEmpty
if some condition {
  something = true
} else {
  something = false
}
something = (some condition)
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now